symfony/http-kernel · error · LogicException

The validation groups expression or closure must return a…

Error message

The validation groups expression or closure must return a string, an array of strings, or a GroupSequence.

What it means

resolveValidationGroups validates the groups computed from the validationGroups expression or closure of a payload attribute. If the callable/expression returns something that is not null, a string, an array, or a GroupSequence, Symfony throws this LogicException.

Solutions

  1. Make the closure/expression return a string, array of strings, or GroupSequence
  2. Cast or normalize the returned value inside the closure
  3. Remove validationGroups to use the default group

Example fix

// before
validationGroups: fn() => 42
// after
validationGroups: fn() => ['Default']
Defensive patterns

Strategy: validation

Validate before calling

$groups = $closure(); if (null !== $groups && !is_string($groups) && !is_array($groups) && !$groups instanceof GroupSequence) { throw new \UnexpectedValueException('bad validationGroups return'); }

Type guard

is_string($groups) || is_array($groups) || $groups instanceof GroupSequence || $groups === null

Try / catch

try { $response = $kernel->handle($request); } catch (\LogicException $e) { if (str_contains($e->getMessage(), 'validation groups expression')) { /* fix return type */ } throw $e; }

Prevention

When it happens

Trigger: A validationGroups closure or expression that returns e.g. an int, an object, or true instead of a string, string[], or GroupSequence instance.

Common situations: Expression strings that evaluate to numbers/booleans, closures returning wrong types after refactoring, or misunderstanding what validationGroups may yield.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13). Data as JSON: /api/errors/cf7cc4ffb54a6019. Report an issue: GitHub.

Appendix: source

Thrown at Controller/ArgumentResolver/RequestPayloadValueResolver.php:340

        foreach ($files as $value) {
            $params[] = $value;
        }

        return $params;
    }

    private function resolveValidationGroups(Expression|string|GroupSequence|\Closure|array|null $validationGroups, ControllerArgumentsEvent $event): string|GroupSequence|array|null
    {
        if ($validationGroups instanceof Expression || $validationGroups instanceof \Closure) {
            $validationGroups = $event->evaluate($validationGroups, $this->expressionLanguage);
        }

        if (null === $validationGroups || \is_string($validationGroups) || $validationGroups instanceof GroupSequence) {
            return $validationGroups;
        }

        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.');
            }

View on GitHub (pinned to aa3a39d728)