symfony/http-kernel · error · LogicException

You must use a URI when using the ESI rendering strategy or…

Error message

You must use a URI when using the ESI rendering strategy or set a URL signer.

What it means

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.

Solutions

  1. Construct the generator with a signer: new FragmentUriGenerator('/_fragment', new UriSigner($secret)).
  2. Pass $sign = false only if you intentionally want unsigned URIs (not recommended for ESI).
  3. Check DI wiring so the framework-injected generator has the signer configured.

Example fix

// before
$generator = new FragmentUriGenerator('/_fragment', null, $requestStack);
// after
$generator = new FragmentUriGenerator('/_fragment', new UriSigner('secret'), $requestStack);
Defensive patterns

Strategy: validation

Validate before calling

if ($sign && null === $signer) { throw new \LogicException('Configure a UriSigner before generating signed fragment URIs.'); }

Try / catch

try { $url = $generator->generate($ref); } catch (\LogicException $e) { // log misconfiguration, fall back to unsigned internal call }

Prevention

When it happens

Trigger: Calling generate($controller, $request, absolute, strict, true) on a generator constructed without a UriSigner argument.

Common situations: Manual FragmentUriGenerator instantiation missing the signer; switching to a rendering strategy that requires signed URIs without updating the service wiring.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13). Data as JSON: /api/errors/d2476e72bda8f8aa. Report an issue: GitHub.

Appendix: source

Thrown at Fragment/FragmentUriGenerator.php:42

 */
final class FragmentUriGenerator implements FragmentUriGeneratorInterface
{
    public function __construct(
        private string $fragmentPath,
        private ?UriSigner $signer = null,
        private ?RequestStack $requestStack = null,
        private \DateTimeInterface|\DateInterval|int $expiration = new \DateInterval('P5Y'),
    ) {
    }

    public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string
    {
        if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) {
            throw new \LogicException('Generating a fragment URL can only be done when handling a Request.');
        }

        if ($sign && null === $this->signer) {
            throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
        }

        if ($strict) {
            $this->checkNonScalar($controller->attributes);
        }

        // We need to forward the current _format and _locale values as we don't have
        // a proper routing pattern to do the job for us.
        // This makes things inconsistent if you switch from rendering a controller
        // to rendering a route if the route pattern does not contain the special
        // _format and _locale placeholders.
        if (!isset($controller->attributes['_format'])) {
            $controller->attributes['_format'] = $request->getRequestFormat();
        }
        if (!isset($controller->attributes['_locale'])) {
            $controller->attributes['_locale'] = $request->getLocale();
        }

View on GitHub (pinned to aa3a39d728)