{"record":{"id":"851f5add7e7e217f","repo":"twigphp/Twig","slug":"malformed-namespaced-template-name-s-expecting-namespace","errorCode":null,"errorMessage":"Malformed namespaced template name \"%s\" (expecting \"@namespace/template_name\").","messagePattern":"Malformed namespaced template name \"(.+?)\" \\(expecting \"@namespace/template_name\"\\)\\.","errorType":"exception","errorClass":"LoaderError","httpStatus":null,"severity":"error","filePath":"src/Loader/FilesystemLoader.php","lineNumber":246,"sourceCode":"        $this->errorCache[$name] = \\sprintf('Unable to find template \"%s\" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));\n\n        if (!$throw) {\n            return null;\n        }\n\n        throw new LoaderError($this->errorCache[$name]);\n    }\n\n    private function normalizeName(string $name): string\n    {\n        return preg_replace('#/{2,}#', '/', str_replace('\\\\', '/', $name));\n    }\n\n    private function parseName(string $name, string $default = self::MAIN_NAMESPACE): array\n    {\n        if (isset($name[0]) && '@' == $name[0]) {\n            if (false === $pos = strpos($name, '/')) {\n                throw new LoaderError(\\sprintf('Malformed namespaced template name \"%s\" (expecting \"@namespace/template_name\").', $name));\n            }\n\n            $namespace = substr($name, 1, $pos - 1);\n            $shortname = substr($name, $pos + 1);\n\n            return [$namespace, $shortname];\n        }\n\n        return [$default, $name];\n    }\n\n    private function validateName(string $name): void\n    {\n        if (str_contains($name, \"\\0\")) {\n            throw new LoaderError('A template name cannot contain NUL bytes.');\n        }\n\n        $name = ltrim($name, '/');","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Loader/FilesystemLoader.php#L228-L264","documentation":"Namespaced template names must follow '@namespace/template_name'. parseName() throws this when a name starts with '@' but contains no '/', so no namespace separator can be found. The default (main) namespace requires no '@' prefix.","triggerScenarios":"Passing a name like '@Blog' (missing '/shortname') to any template lookup; programmatically building names with an empty shortname; concatenating variables into template names incorrectly.","commonSituations":"Dynamic template name construction where a variable is empty; user-supplied template names lacking the namespace separator; confusing the '@' syntax with directory paths.","solutions":["Use the full '@namespace/template' form, e.g. '@Blog/post.html.twig'.","If the template is in the main namespace, drop the '@' prefix entirely.","Sanitize/dynamically constructed names: ensure the '/separator and non-empty shortname exist before rendering."],"exampleFix":"// before\n$twig->render('@Blog'.$page); // '@Blogabout' — no slash\n// after\n$twig->render('@Blog/'.$page.'.html.twig');","handlingStrategy":"validation","validationCode":"if (str_starts_with($name, '@') && !str_contains($name, '/')) { throw new \\InvalidArgumentException(\"Template name '$name' must be '@ns/template'\"); }","typeGuard":"function isWellFormedNamespacedName(string $name): bool { return !(str_starts_with($name, '@') && !str_contains($name, '/')); }","tryCatchPattern":"try { $twig->render($name); } catch (Twig\\Error\\LoaderError $e) { if (str_contains($e->getMessage(), 'Malformed namespaced')) { // fix name format or drop '@' for main namespace } }","preventionTips":["Validate dynamically built template names before render","Never concatenate '@' + namespace without appending '/template'","Favor template name maps over raw string interpolation"],"tags":["twig","namespace","invalid-name-format"],"backgroundTag":"invalid-argument-format","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}