{"record":{"id":"d2476e72bda8f8aa","repo":"symfony/http-kernel","slug":"you-must-use-a-uri-when-using-the-esi-rendering-strategy-or","errorCode":null,"errorMessage":"You must use a URI when using the ESI rendering strategy or set a URL signer.","messagePattern":"You must use a URI when using the ESI rendering strategy or set a URL signer\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"Fragment/FragmentUriGenerator.php","lineNumber":42,"sourceCode":" */\nfinal class FragmentUriGenerator implements FragmentUriGeneratorInterface\n{\n    public function __construct(\n        private string $fragmentPath,\n        private ?UriSigner $signer = null,\n        private ?RequestStack $requestStack = null,\n        private \\DateTimeInterface|\\DateInterval|int $expiration = new \\DateInterval('P5Y'),\n    ) {\n    }\n\n    public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string\n    {\n        if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) {\n            throw new \\LogicException('Generating a fragment URL can only be done when handling a Request.');\n        }\n\n        if ($sign && null === $this->signer) {\n            throw new \\LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');\n        }\n\n        if ($strict) {\n            $this->checkNonScalar($controller->attributes);\n        }\n\n        // We need to forward the current _format and _locale values as we don't have\n        // a proper routing pattern to do the job for us.\n        // This makes things inconsistent if you switch from rendering a controller\n        // to rendering a route if the route pattern does not contain the special\n        // _format and _locale placeholders.\n        if (!isset($controller->attributes['_format'])) {\n            $controller->attributes['_format'] = $request->getRequestFormat();\n        }\n        if (!isset($controller->attributes['_locale'])) {\n            $controller->attributes['_locale'] = $request->getLocale();\n        }\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/symfony/http-kernel/blob/aa3a39d7286a62cdfea98f0e69c651a3da6e36cf/Fragment/FragmentUriGenerator.php#L24-L60","documentation":"FragmentUriGenerator::generate() throws LogicException when $sign is true but no UrlSigner was configured. Fragment URLs must be signed (with an _hash parameter) so untrusted clients cannot trigger arbitrary controller rendering via ESI/SSI.","triggerScenarios":"Calling generate($controller, $request, absolute, strict, true) on a generator constructed without a UriSigner argument.","commonSituations":"Manual FragmentUriGenerator instantiation missing the signer; switching to a rendering strategy that requires signed URIs without updating the service wiring.","solutions":["Construct the generator with a signer: new FragmentUriGenerator('/_fragment', new UriSigner($secret)).","Pass $sign = false only if you intentionally want unsigned URIs (not recommended for ESI).","Check DI wiring so the framework-injected generator has the signer configured."],"exampleFix":"// before\n$generator = new FragmentUriGenerator('/_fragment', null, $requestStack);\n// after\n$generator = new FragmentUriGenerator('/_fragment', new UriSigner('secret'), $requestStack);","handlingStrategy":"validation","validationCode":"if ($sign && null === $signer) { throw new \\LogicException('Configure a UriSigner before generating signed fragment URIs.'); }","typeGuard":null,"tryCatchPattern":"try { $url = $generator->generate($ref); } catch (\\LogicException $e) { // log misconfiguration, fall back to unsigned internal call }","preventionTips":["Always wire a UriSigner when using ESI/SSI rendering","Review service definitions after strategy changes","Never pass sign=false just to silence the error in production"],"tags":["php","symfony","fragment","signing","configuration"],"backgroundTag":"missing-required-config","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"}