{"record":{"id":"0d2c99b8cf61c830","repo":"symfony/http-kernel","slug":"mapqueryparameter-cannot-be-used-on-controller-argument-s-s","errorCode":null,"errorMessage":"#[MapQueryParameter] cannot be used on controller argument \"%s$%s\" of type \"%s\"; one of array, string, int, float, bool, uid or \\BackedEnum should be used.","messagePattern":"#\\[MapQueryParameter\\] cannot be used on controller argument \"(.+?)\\$(.+?)\" of type \"(.+?)\"; one of array, string, int, float, bool, uid or \\\\BackedEnum should be used\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"Controller/ArgumentResolver/QueryParameterValueResolver.php","lineNumber":117,"sourceCode":"            // Stage the raw value under the argument name so that a resolver able to build this type,\n            // such as DateTimeValueResolver or EntityValueResolver, picks it up from the attributes.\n            $request->attributes->set($argument->getName(), $value);\n\n            throw new NearMissValueResolverException(\\sprintf('#[MapQueryParameter] cannot build controller argument \"$%s\" of type \"%s\" by itself; no resolver converted the staged value.', $argument->getName(), $type));\n        }\n\n        $enumType = null;\n        $filter = match ($type) {\n            'array' => \\FILTER_DEFAULT,\n            'string' => isset($attribute->options['regexp']) ? \\FILTER_VALIDATE_REGEXP : \\FILTER_DEFAULT,\n            'int' => \\FILTER_VALIDATE_INT,\n            'float' => \\FILTER_VALIDATE_FLOAT,\n            'bool' => \\FILTER_VALIDATE_BOOL,\n            'uid' => \\FILTER_DEFAULT,\n            default => match ($enumType = is_subclass_of($type, \\BackedEnum::class) ? (new \\ReflectionEnum($type))->getBackingType()->getName() : null) {\n                'int' => \\FILTER_VALIDATE_INT,\n                'string' => \\FILTER_DEFAULT,\n                default => throw new \\LogicException(\\sprintf('#[MapQueryParameter] cannot be used on controller argument \"%s$%s\" of type \"%s\"; one of array, string, int, float, bool, uid or \\BackedEnum should be used.', $argument->isVariadic() ? '...' : '', $argument->getName(), $type ?? 'mixed')),\n            },\n        };\n\n        $value = filter_var($value, $attribute->filter ?? $filter, $options);\n\n        if (null !== $enumType && null !== $value) {\n            $enumFrom = static function ($value) use ($type) {\n                if (!\\is_string($value) && !\\is_int($value)) {\n                    return null;\n                }\n\n                try {\n                    return $type::from($value);\n                } catch (\\ValueError) {\n                    return null;\n                }\n            };\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/symfony/http-kernel/blob/aa3a39d7286a62cdfea98f0e69c651a3da6e36cf/Controller/ArgumentResolver/QueryParameterValueResolver.php#L99-L135","documentation":"QueryParameterValueResolver resolves controller arguments annotated with #[MapQueryParameter] by mapping the argument's type to a PHP filter. It throws LogicException when the declared type is not one of array, string, int, float, bool, uid, or a BackedEnum, because no filter can validate such a value.","triggerScenarios":"Using #[MapQueryParameter] on an argument typed as an object (other than \\BackedEnum subclass), a UnionType, 'mixed', a non-backed (pure) Enum, or a class like DateTimeImmutable.","commonSituations":"Mapping query params to DateTime or custom value objects; using enum cases without backing values; forgetting that only int-/string-backed enums are supported; variadic and nullable variants still require supported base types.","solutions":["Change the argument type to one of array, string, int, float, bool, \\Symfony\\Component\\Uid\\Uid-type (uid), or a backed enum.","For non-backed enums, add a backing type (int|string) to the enum.","For objects like DateTime, accept a string and convert inside the controller, or write a custom value resolver."],"exampleFix":"// before\npublic function list(#[MapQueryParameter] \\DateTimeImmutable $since) {}\n// after\npublic function list(#[MapQueryParameter] string $since) {}\n$since = new \\DateTimeImmutable($since);","handlingStrategy":"type-guard","validationCode":"$type = $param->getType();\n$allowed = ['array','string','int','float','bool'];\n$ok = $type instanceof \\ReflectionNamedType && (in_array($type->getName(), $allowed, true) || is_subclass_of($type->getName(), \\BackedEnum::class) || is_subclass_of($type->getName(), \\Symfony\\Component\\Uid\\AbstractUid::class));","typeGuard":"function isMapQueryParameterCompatible(\\ReflectionParameter $p): bool\n{\n    $t = $p->getType();\n    if (!$t instanceof \\ReflectionNamedType) return false;\n    return in_array($t->getName(), ['array','string','int','float','bool'], true)\n        || is_subclass_of($t->getName(), \\BackedEnum::class)\n        || is_subclass_of($t->getName(), \\Symfony\\Component\\Uid\\AbstractUid::class);\n}","tryCatchPattern":"try { $args = $resolver->getArguments($request, $controller); } catch (\\LogicException $e) { /* retype argument to a supported scalar/backed-enum */ }","preventionTips":["Only use supported scalar types or backed enums with #[MapQueryParameter]","Convert strings to DateTime/objects inside the controller","Prefer int/string-backed enums for filterable query flags"],"tags":["symfony","controller","query-parameter","attributes"],"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"}