@@ -388,7 +388,14 @@ private function preDispatch($eventName, Event $event)
388
388
break ;
389
389
case KernelEvents::TERMINATE :
390
390
$ token = $ event ->getResponse ()->headers ->get ('X-Debug-Token ' );
391
- $ this ->stopwatch ->openSection ($ token );
391
+ // There is a very special case when using builtin AppCache class as kernel wrapper, in the case
392
+ // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A].
393
+ // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID
394
+ // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception
395
+ // which must be caught.
396
+ try {
397
+ $ this ->stopwatch ->openSection ($ token );
398
+ } catch (\LogicException $ e ) {}
392
399
break ;
393
400
}
394
401
}
@@ -410,7 +417,11 @@ private function postDispatch($eventName, Event $event)
410
417
break ;
411
418
case KernelEvents::TERMINATE :
412
419
$ token = $ event ->getResponse ()->headers ->get ('X-Debug-Token ' );
413
- $ this ->stopwatch ->stopSection ($ token );
420
+ // In the special case described in the `preDispatch` method above, the `$token` section
421
+ // does not exist, then closing it throws an exception which must be caught.
422
+ try {
423
+ $ this ->stopwatch ->stopSection ($ token );
424
+ } catch (\LogicException $ e ) {}
414
425
// The children profiles have been updated by the previous 'kernel.response'
415
426
// event. Only the root profile need to be updated with the 'kernel.terminate'
416
427
// timing informations.
0 commit comments