{"record":{"id":"7220c98239d48d70","repo":"symfony/routing","slug":"a-placeholder-name-must-be-a-string-d-given-did-you-forget-7220c9","errorCode":null,"errorMessage":"A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement \"%s\" in \"%s\"?","messagePattern":"A placeholder name must be a string \\((.+?) given\\)\\. Did you forget to specify the placeholder key for the requirement \"(.+?)\" in \"(.+?)\"\\?","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"Loader/AttributeClassLoader.php","lineNumber":330,"sourceCode":"\n            if (null !== $attr->methods) {\n                $globals['methods'] = $attr->methods;\n            }\n\n            if (null !== $attr->host) {\n                $globals['host'] = $attr->host;\n            }\n\n            if (null !== $attr->condition) {\n                $globals['condition'] = $attr->condition;\n            }\n\n            $globals['priority'] = $attr->priority ?? 0;\n            $globals['env'] = $attr->envs;\n\n            foreach ($globals['requirements'] as $placeholder => $requirement) {\n                if (\\is_int($placeholder)) {\n                    throw new \\InvalidArgumentException(\\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement \"%s\" in \"%s\"?', $placeholder, $requirement, $class->getName()));\n                }\n            }\n        }\n\n        return $globals;\n    }\n\n    private function resetGlobals(): array\n    {\n        return [\n            'path' => null,\n            'localized_paths' => [],\n            'requirements' => [],\n            'options' => [],\n            'defaults' => [],\n            'schemes' => [],\n            'methods' => [],\n            'host' => '',","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/AttributeClassLoader.php#L312-L348","documentation":"getGlobals validates requirement keys coming from a class-level #[Route] attribute before merging them into globals. Integer (positional) keys mean the requirement was given without a placeholder name, so it throws InvalidArgumentException naming the class.","triggerScenarios":"A controller class annotated #[Route(path: '/blog', requirements: ['\\d+'])] with a positional requirement, triggering validation of class-level globals during load().","commonSituations":"Missing named key on class-level requirements; assuming class-level requirements may be positional; copy-paste of a requirement array without its keys.","solutions":["Add explicit placeholder keys to the class-level #[Route] requirements","Check each #[Route] attribute on the controller class for named requirement keys","Remember requirements are merged with method-level ones; both sides need string keys"],"exampleFix":"// before\n#[Route('/blog', requirements: ['\\d+'])]\n// after\n#[Route('/blog', requirements: ['page' => '\\d+'])]","handlingStrategy":"validation","validationCode":"foreach ($classAttr->requirements as $k => $v) { if (is_int($k)) throw new \\InvalidArgumentException('Class-level requirement needs named key'); }","typeGuard":"function allRequirementsNamed(array $requirements): bool { return arrayevery(fn($k) => is_string($k), array_keys($requirements)); }","tryCatchPattern":"try { $routes = $loader->load($file); } catch (\\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'placeholder name must be a string')) { /* fix class attribute */ } throw $e; }","preventionTips":["Never use positional requirement arrays, even on class-level #[Route]","Code-review checklist item for requirements keys","Static analysis rule for integer keys in requirements"],"tags":["routing","php-attributes","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"83fa223250b50f4f018c011e101c330e65ac63cc","analyzedAt":"2026-09-14T03:19:46.280Z","contentChangedAt":"2026-09-14T03:19:46.280Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}