{"record":{"id":"aef7a71ad637b7a6","repo":"symfony/http-kernel","slug":"missing-header-s","errorCode":null,"errorMessage":"Missing header \"%s\".","messagePattern":"Missing header \"(.+?)\"\\.","errorType":"http","errorClass":"HttpException","httpStatus":422,"severity":"error","filePath":"Controller/ArgumentResolver/RequestHeaderValueResolver.php","lineNumber":44,"sourceCode":"    {\n        if (!$attribute = $argument->getAttributesOfType(MapRequestHeader::class)[0] ?? null) {\n            return [];\n        }\n\n        $type = $argument->getType();\n        $name = $attribute->name ?? strtolower(preg_replace('/[a-z]\\K[A-Z]/', '-$0', $argument->getName()));\n\n        if (!\\in_array($type, ['string', 'array', AcceptHeader::class])) {\n            if (null === $type || $argument->isVariadic() || !class_exists($type) && !interface_exists($type)) {\n                throw new \\LogicException(\\sprintf('Could not resolve the argument typed \"%s\". Valid types are \"array\", \"string\" or \"%s\".', $type, AcceptHeader::class));\n            }\n\n            if (!$request->headers->has($name)) {\n                if ($argument->isNullable() || $argument->hasDefaultValue()) {\n                    return [];\n                }\n\n                throw HttpException::fromStatusCode($attribute->validationFailedStatusCode, \\sprintf('Missing header \"%s\".', $name));\n            }\n\n            // Stage the raw header under the argument name so that a resolver able to build this type,\n            // such as DateTimeValueResolver or UidValueResolver, picks it up from the attributes.\n            $request->attributes->set($argument->getName(), $request->headers->get($name));\n\n            throw new NearMissValueResolverException(\\sprintf('#[MapRequestHeader] cannot build controller argument \"$%s\" of type \"%s\" by itself; no resolver converted the staged value.', $argument->getName(), $type));\n        }\n\n        $value = null;\n\n        if ($request->headers->has($name)) {\n            $value = match ($type) {\n                'string' => $request->headers->get($name),\n                'array' => match (strtolower($name)) {\n                    'accept' => $request->getAcceptableContentTypes(),\n                    'accept-charset' => $request->getCharsets(),\n                    'accept-language' => $request->getLanguages(),","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/symfony/http-kernel/blob/aa3a39d7286a62cdfea98f0e69c651a3da6e36cf/Controller/ArgumentResolver/RequestHeaderValueResolver.php#L26-L62","documentation":"Symfony's RequestHeaderValueResolver throws this HttpException when a controller argument mapped with #[MapRequestHeader] to a complex type (e.g. DateTime, Uid) is absent from the request headers, and the argument is neither nullable nor has a default value. The resolver aborts with the attribute's validationFailedStatusCode (default 422) because it cannot produce the argument value.","triggerScenarios":"A controller declares an argument like #[MapRequestHeader] \\DateTimeImmutable $lastModified or #[MapRequestHeader] Uid $requestId, and the incoming request does not contain the corresponding header (name derived from the parameter in kebab-case, e.g. 'last-modified'), while the parameter is non-nullable with no default.","commonSituations":"Clients omitting a mandatory header (API version, trace id); header name mismatch after renaming a controller parameter since the header name is derived from it; tests or curl calls missing -H flags; proxies or CORS preflight policies stripping custom headers.","solutions":["Send the required header with the exact name shown in the error message.","Make the controller argument nullable (e.g. ?\\DateTimeImmutable) so a missing header skips resolution.","Give the argument a default value so absence is tolerated.","Pass the header name explicitly via #[MapRequestHeader('X-Request-Id')] if the kebab-case derivation does not match what clients send."],"exampleFix":"// before\npublic function show(#[MapRequestHeader] \\DateTimeImmutable $lastModified) {}\n// after\npublic function show(#[MapRequestHeader] ?\\DateTimeImmutable $lastModified = null) {}","handlingStrategy":"validation","validationCode":"// Server side: guard before relying on the argument\npublic function show(Request $request, #[MapRequestHeader] ?\\DateTimeImmutable $lastModified = null) {\n    if (null === $lastModified && $request->headers->has('last-modified') === false) {\n        // handle absent header explicitly\n    }\n}\n// Client side, before sending:\nif (!isset($headers['X-Request-Id'])) {\n    throw new \\LogicException('Header X-Request-Id is required');\n}","typeGuard":"function hasHeader(Request $request, string $name): bool {\n    return $request->headers->has($name);\n}","tryCatchPattern":"try {\n    $response = $kernel->handle($request);\n} catch (HttpException $e) {\n    if (str_contains($e->getMessage(), 'Missing header ')) {\n        return new JsonResponse(['error' => $e->getMessage()], 422);\n    }\n    throw $e;\n}","preventionTips":["Always send required custom headers in clients and functional tests (curl -H, Request::headers->set).","Prefer explicit header names in #[MapRequestHeader('Name')] over parameter-name derivation.","Make optional headers nullable or defaulted in the controller signature.","Document required headers in the API spec and validate at the client boundary.","Check proxies/CORS config for custom-header stripping (Access-Control-Allow-Headers)."],"tags":["symfony","http-header","controller-argument","validation"],"backgroundTag":"missing-required-argument","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"}