{"record":{"id":"0cebfdeb8e394600","repo":"symfony/http-kernel","slug":"passing-non-scalar-values-as-part-of-uri-attributes-to-the","errorCode":null,"errorMessage":"Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.","messagePattern":"Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported\\. Use a different rendering strategy or pass scalar values\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"Fragment/AbstractSurrogateFragmentRenderer.php","lineNumber":61,"sourceCode":"     *\n     * Additional available options:\n     *\n     *  * alt: an alternative URI to render in case of an error\n     *  * comment: a comment to add when returning the surrogate tag\n     *  * absolute_uri: whether to generate an absolute URI or not. Default is false\n     *\n     * Note, that not all surrogate strategies support all options. For now\n     * 'alt' and 'comment' are only supported by ESI.\n     *\n     * @see Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface\n     */\n    public function render(string|ControllerReference $uri, Request $request, array $options = []): Response\n    {\n        if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {\n            $request->attributes->set('_check_controller_is_allowed', true);\n\n            if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) {\n                throw new \\InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.');\n            }\n\n            return $this->inlineStrategy->render($uri, $request, $options);\n        }\n\n        $absolute = $options['absolute_uri'] ?? false;\n\n        if ($uri instanceof ControllerReference) {\n            $uri = $this->generateSignedFragmentUri($uri, $request, $absolute);\n        }\n\n        $alt = $options['alt'] ?? null;\n        if ($alt instanceof ControllerReference) {\n            $alt = $this->generateSignedFragmentUri($alt, $request, $absolute);\n        }\n\n        $tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? false, $options['comment'] ?? '');\n","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/symfony/http-kernel/blob/aa3a39d7286a62cdfea98f0e69c651a3da6e36cf/Fragment/AbstractSurrogateFragmentRenderer.php#L43-L79","documentation":"AbstractSurrogateFragmentRenderer falls back to the inline strategy when the request has no ESI/SSI capability. ControllerReference attributes must be embedded in a URI in that path, which only works for scalars; non-scalar attributes trigger an InvalidArgumentException.","triggerScenarios":"Calling render() with a ControllerReference whose $attributes array contains arrays/objects (e.g. ['filters' => ['a','b']]) on a request without surrogate capability, causing the inline fallback path.","commonSituations":"Rendering ESI/SSI fragments without an ESI/SSI-capable request (no surrogate capability headers in tests); passing nested arrays or objects as fragment attributes expecting object passing like hinclude/inline.","solutions":["Ensure the surrogate is configured and the request has surrogate capability (Request::setTrustedProxies + ESI listener) so URIs are generated natively.","Pass only scalar attribute values, or serialize complex data (e.g. json_encode) into a scalar attribute.","Use a renderer that supports non-scalar attributes, such as the inline fragment renderer directly."],"exampleFix":"// before\n$renderer->render(new ControllerReference('App::foo', [], ['filters' => ['a','b']]), $request);\n// after\n$renderer->render(new ControllerReference('App::foo', [], ['filters' => 'a,b']), $request);","handlingStrategy":"type-guard","validationCode":"function hasNonScalars(array $attrs): bool {\n  foreach ($attrs as $v) { if (!is_scalar($v) && $v !== null) return true; }\n  return false;\n}\nif (hasNonScalars($ref->attributes) && !$surrogate->hasSurrogateCapability($request)) { /* flatten or skip */ }","typeGuard":"$allScalar = fn(array $a): bool => array_reduce($a, fn($c,$v) => $c && (is_scalar($v) || $v === null), true);","tryCatchPattern":"try { $resp = $renderer->render($uri, $request); } catch (\\InvalidArgumentException $e) { $resp = $inlineRenderer->render($uri, $request); }","preventionTips":["Keep fragment attributes scalar-only (strings, ints, bools)","Serialize complex data before attaching to a ControllerReference","Verify surrogate capability in the environment where fragments render"],"tags":["fragments","esi","ssi","symfony"],"backgroundTag":"invalid-argument-value","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"}