{"record":{"id":"8f2c55b90487fa55","repo":"symfony/http-kernel","slug":"cannot-mix-virtual-and-http-requests","errorCode":null,"errorMessage":"Cannot mix virtual and HTTP requests.","messagePattern":"Cannot mix virtual and HTTP requests\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"Debug/VirtualRequestStack.php","lineNumber":35,"sourceCode":"/**\n * A stack able to deal with virtual requests.\n *\n * @internal\n *\n * @author Jules Pietri <jules@heahprod.com>\n */\nfinal class VirtualRequestStack extends RequestStack\n{\n    public function __construct(\n        private readonly RequestStack $decorated,\n    ) {\n    }\n\n    public function push(Request $request): void\n    {\n        if ($request->attributes->has('_virtual_type')) {\n            if ($this->decorated->getCurrentRequest()) {\n                throw new \\LogicException('Cannot mix virtual and HTTP requests.');\n            }\n\n            parent::push($request);\n\n            return;\n        }\n\n        $this->decorated->push($request);\n    }\n\n    public function pop(): ?Request\n    {\n        return $this->decorated->pop() ?? parent::pop();\n    }\n\n    public function getCurrentRequest(): ?Request\n    {\n        return $this->decorated->getCurrentRequest() ?? parent::getCurrentRequest();","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/symfony/http-kernel/blob/aa3a39d7286a62cdfea98f0e69c651a3da6e36cf/Debug/VirtualRequestStack.php#L17-L53","documentation":"Symfony's VirtualRequestStack decorates the standard RequestStack to manage 'virtual' requests (marked with a _virtual_type attribute, used e.g. by internal sub-operations). Its push() throws LogicException if a virtual request is pushed while a real HTTP request is currently active — virtual and real requests cannot coexist on the stack. This enforces the invariant that the stack holds one consistent kind of request at a time.","triggerScenarios":"Calling $stack->push($virtualRequest) while getCurrentRequest() returns a live HTTP request; mixing template/asset virtual request pushes inside a normal HTTP kernel handle() cycle; custom code (e.g. a listener) pushing a virtual request mid-HTTP-request.","commonSituations":"Integrating legacy VirtualRequestStack-based code (assets/templating-era Symfony) with modern HTTP-kernel flows; third-party bundles assuming virtual requests can be nested inside HTTP handling; custom error/fragment handlers pushing virtual requests.","solutions":["Do not push virtual requests while a real request is on the stack — ensure $this->decorated->getCurrentRequest() is null before pushing.","Complete (pop) the HTTP request before pushing virtual ones, or restructure to use sub-requests via HttpKernel::handle() with SUB_REQUEST type instead.","Audit listeners/subscribers that call push() and remove or guard them when a master request exists.","If migrating, replace virtual request usage with the modern RequestStack/fragment handling in current Symfony."],"exampleFix":"// before\nif ($event->isMasterRequest()) {\n    $this->virtualStack->push($virtualRequest);\n}\n// after\nif (null === $this->requestStack->getCurrentRequest()) {\n    $this->virtualStack->push($virtualRequest);\n}","handlingStrategy":"try-catch","validationCode":"if ($request->attributes->has('_virtual_type') && null !== $decoratedStack->getCurrentRequest()) {\n    throw new \\RuntimeException('Cannot push a virtual request inside an active HTTP request.');\n}","typeGuard":"function canPushVirtual(\\Symfony\\Component\\HttpFoundation\\RequestStack $stack, \\Symfony\\Component\\HttpFoundation\\Request $r): bool\n{\n    return !$r->attributes->has('_virtual_type') || null === $stack->getCurrentRequest();\n}","tryCatchPattern":"try {\n    $virtualStack->push($virtualRequest);\n} catch (\\LogicException $e) {\n    $logger->warning('Skipped virtual push: '.$e->getMessage());\n    return; // or handle via HttpKernel sub-request instead\n}","preventionTips":["Never push virtual requests from listeners that run during a live HTTP request.","Prefer HttpKernel::handle() with SUB_REQUEST over virtual-request tricks in modern Symfony.","Guard all push() call sites with a getCurrentRequest() === null check when dealing with virtual types.","Document which parts of your app operate outside the HTTP cycle and may legitimately use virtual requests."],"tags":["symfony","request-stack","virtual-request","logic-exception"],"backgroundTag":"invalid-state-transition","analyzedSha":"aa3a39d7286a62cdfea98f0e69c651a3da6e36cf","analyzedAt":"2026-09-13T18:03:36.509Z","contentChangedAt":"2026-09-13T18:03:36.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}