symfony/http-kernel · error · LogicException
Validation groups must be strings.
Error message
Validation groups must be strings.
What it means
After excluding Expression, Closure, and GroupSequence elements, every remaining element of a validation-groups array must be a plain string. Any other scalar/object element causes this LogicException.
Solutions
- Convert non-string group values to strings (e.g. $enum->value)
- Fix the group constants to be string constants
- Filter/normalize the groups array before returning it from the closure
Example fix
// before validationGroups: fn() => [Group::Strict, 'Default'] // after validationGroups: fn() => [Group::Strict->value, 'Default']
Defensive patterns
Strategy: validation
Validate before calling
foreach ($groups as $g) { if (!is_string($g)) { throw new \InvalidArgumentException('group must be string'); } } Type guard
is_array($groups) && array_all($groups, 'is_string')
Try / catch
try { $response = $kernel->handle($request); } catch (\LogicException $e) { if (str_contains($e->getMessage(), 'must be strings')) { /* stringify group values */ } throw $e; } Prevention
- Use string constants for groups
- Cast backed enums with ->value
- Validate the groups array shape in unit tests
When it happens
Trigger: Passing validationGroups: ['Default', 42] or an array containing null/enum objects to a payload attribute's validationGroups.
Common situations: Using integer constants for groups, forgetting to cast backed enums to strings, or building the groups array dynamically with mixed values.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- The validation groups expression or closure must return a…
- Nested expressions in validation groups are not supported…
- Nested closures in validation groups are not supported. Use…
- GroupSequence cannot be used inside an array of validation…
- The action argument "...$%1$s" is required to be an array…
AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13).
Data as JSON: /api/errors/38a07d579400ec36.
Report an issue: GitHub.
Appendix: source
Thrown at Controller/ArgumentResolver/RequestPayloadValueResolver.php:357
if (!\is_array($validationGroups)) {
throw new \LogicException('The validation groups expression or closure must return a string, an array of strings, or a GroupSequence.');
}
foreach ($validationGroups as $group) {
if ($group instanceof Expression) {
throw new \LogicException('Nested expressions in validation groups are not supported. Use a single Expression or a list of strings (or a GroupSequence) instead.');
}
if ($group instanceof \Closure) {
throw new \LogicException('Nested closures in validation groups are not supported. Use a single Closure or a list of strings (or a GroupSequence) instead.');
}
if ($group instanceof GroupSequence) {
throw new \LogicException('GroupSequence cannot be used inside an array of validation groups. Pass the GroupSequence as the top-level validationGroups value instead.');
}
if (!\is_string($group)) {
throw new \LogicException('Validation groups must be strings.');
}
}
return $validationGroups;
}
private static function hasNonStringScalar(array $data): bool
{
$stack = [$data];
while ($stack) {
foreach (array_pop($stack) as $v) {
if (\is_array($v)) {
$stack[] = $v;
} elseif (!\is_string($v) && !\is_object($v)) {
// uploaded files are merged into the payload of a "form" request; being objects,
// they are not scalars and must not make the payload look like a typed one
return true;View on GitHub (pinned to aa3a39d728)