Error in batch process: Failed to start the session because headers have already been sent

Created on 7 April 2025, 3 months ago

I am using single_content_sync to import stuff and then receive this error when the batch process is almost finished:

RuntimeException: Failed to start the session because headers have already been sent by "C:\Users\my_pc\www\my_project\drupal10\vendor\symfony\http-foundation\Response.php" at line 1315. in Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() (line 132 of C:\Users\my_pc\www\my_project\drupal10\vendor\symfony\http-foundation\Session\Storage\NativeSessionStorage.php)
#0 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\Session\SessionManager.php(162): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start()
#1 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\Session\SessionManager.php(127): Drupal\Core\Session\SessionManager->startNow()
#2 C:\Users\my_pc\www\my_project\drupal10\vendor\symfony\http-foundation\Session\Session.php(59): Drupal\Core\Session\SessionManager->start()
#3 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\Batch\BatchStorage.php(72): Symfony\Component\HttpFoundation\Session\Session->start()
#4 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\ProxyClass\Batch\BatchStorage.php(75): Drupal\Core\Batch\BatchStorage->load('172')
#5 C:\Users\my_pc\www\my_project\drupal10\web\core\modules\system\src\Controller\BatchController.php(96): Drupal\Core\ProxyClass\Batch\BatchStorage->load('172')
#6 [internal function]: Drupal\system\Controller\BatchController->batchPageTitle(Object(Symfony\Component\HttpFoundation\Request))
#7 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\Controller\TitleResolver.php(58): call_user_func_array(Array, Array)
#8 C:\Users\my_pc\www\my_project\drupal10\web\modules\contrib\simple_access_log\src\Controller\SimpleAccessLog.php(102): Drupal\Core\Controller\TitleResolver->getTitle(Object(Symfony\Component\HttpFoundation\Request), Object(Symfony\Component\Routing\Route))
#9 C:\Users\my_pc\www\my_project\drupal10\web\modules\contrib\simple_access_log\src\EventSubscriber\SimpleAccessLogSubscriber.php(24): Drupal\simple_access_log\Controller\SimpleAccessLog::logValues()
#10 [internal function]: Drupal\simple_access_log\EventSubscriber\SimpleAccessLogSubscriber->executeLogFunction(Object(Symfony\Component\HttpKernel\Event\TerminateEvent), 'kernel.terminat...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#11 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\TerminateEvent), 'kernel.terminat...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#12 C:\Users\my_pc\www\my_project\drupal10\vendor\symfony\http-kernel\HttpKernel.php(115): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\TerminateEvent), 'kernel.terminat...')
#13 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\StackMiddleware\StackedHttpKernel.php(66): Symfony\Component\HttpKernel\HttpKernel->terminate(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\LocalRedirectResponse))
#14 C:\Users\my_pc\www\my_project\drupal10\web\core\lib\Drupal\Core\DrupalKernel.php(715): Drupal\Core\StackMiddleware\StackedHttpKernel->terminate(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\LocalRedirectResponse))
#15 C:\Users\my_pc\www\my_project\drupal10\web\index.php(22): Drupal\Core\DrupalKernel->terminate(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\LocalRedirectResponse))
#16 {main}

🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇳🇱Netherlands koosvdkolk

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @koosvdkolk
  • 🇳🇱Netherlands koosvdkolk

    So I took a dive in this issue. The problem arises at the very end of a batch process, so the last call closing the whole thing.

    SimpleAccessLog.php around line 103 has

    if ($route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) {
      $access_log['title'] = (is_array(\Drupal::service('title_resolver')->getTitle($request, $route))?\Drupal::service('title_resolver')->getTitle($request, $route)['#markup']:\Drupal::service('title_resolver')->getTitle($request, $route));
    }
    

    This calls the title resolver service.

    In class TitleResolver::getTitle it will try to obtain the route's title dynamically when in a batch process. Around line 56

    if ($callback = $route->getDefault('_title_callback')) {
      $callable = $this->controllerResolver->getControllerFromDefinition($callback);
    
      $arguments = $this->argumentResolver->getArguments($request, $callable);
      $route_title = call_user_func_array($callable, $arguments);
    }
    

    $callable has the value of 'batchPageTitle'. This is a function of class BatchController. Around line 87

    public function batchPageTitle(Request $request) {
      $batch = &batch_get();
    
      if (!($request_id = $request->query->get('id'))) {
        return '';
      }
    
      // Retrieve the current state of the batch.
      if (!$batch) {
        $batch = $this->batchStorage->load($request_id);
       }
       ...
    

    As $batch will be 'NULL' at the end of the batch process, it will call the batchStorage to load itself. The BatchStorage's 'load' function will then start the session around line 72, which will trigger the error

    /**
     * {@inheritdoc}
     */
    public function load($id) {
      // Ensure that a session is started before using the CSRF token generator.
      $this->session->start();
      ...
    
  • 🇳🇱Netherlands koosvdkolk

    Workaround: Exclude the "/batch" path in admin/config/system/simple_access_log

Production build 0.71.5 2024