symfony/routing · error · InvalidArgumentException
" " is not a "BackedEnum" class.
Error message
"%s" is not a "BackedEnum" class.
What it means
Requirement/EnumRequirement wraps a BackedEnum (or its cases) into a route requirement that validates path variables. When a string is passed it must be a class-string of a BackedEnum subclass; otherwise InvalidArgumentException is thrown. Plain (non-backed) enums or totally unrelated class names are rejected because their values cannot be turned into string route requirements.
Solutions
- Pass a backed enum class: make the enum 'enum Status: string' or 'enum Status: int'.
- Use one of the enum's case values or ::cases() array form instead of an unsupported class.
- Fix the class-string typo if it was intended to be a backed enum.
Example fix
// before
new EnumRequirement(PlainStatus::class); // plain enum, not backed
// after
enum Status: string { case Active = 'active'; }
new EnumRequirement(Status::class); Defensive patterns
Strategy: validation
Validate before calling
if (!(is_a($enumClass, \BackedEnum::class, true))) { throw new \InvalidArgumentException('$enumClass must be a BackedEnum class-string'); }
new EnumRequirement($enumClass); Type guard
function isBackedEnumClass(mixed $c): bool { return is_string($c) && is_a($c, \BackedEnum::class, true); } Try / catch
try { $req = new EnumRequirement($cases); } catch (\InvalidArgumentException $e) { $req = null; // enum is not backed; convert or fix the enum } Prevention
- Only reference backed (string/int) enums in route requirements.
- Never downgrade a backed enum to a plain enum without updating requirements.
- Add a unit test constructing all EnumRequirements from your enum classes.
When it happens
Trigger: new EnumRequirement(Status::class) where Status is a unit enum (not backed) or a non-enum class; typo in the class name; using an interface or abstract class name.
Common situations: Upgrading to Symfony's EnumRequirement and pointing it at a legacy plain enum; copy-pasting a class-string of a DTO; refactoring a backed enum into a plain one and forgetting the requirement.
Understand the failure class
Background: "invalid argument", "unknown mode", "not supported": invalid enum-like argument errors explained — this error's family across 19 libraries.
Related errors
- Parameter " " for route " " must match " " (" " given) to…
- Parameters for route
- Route aliases cannot be used on non-invokable class
- The " ()" method must not be called.
- The return value in config file
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/b0fda149dd420e66.
Report an issue: GitHub.
Appendix: source
Thrown at Requirement/EnumRequirement.php:29
namespace Symfony\Component\Routing\Requirement;
use Symfony\Component\Routing\Exception\InvalidArgumentException;
final class EnumRequirement implements \Stringable
{
private string $requirement;
/**
* @template T of \BackedEnum
*
* @param class-string<T>|list<T> $cases
*/
public function __construct(string|array $cases = [])
{
if (\is_string($cases)) {
if (!is_subclass_of($cases, \BackedEnum::class, true)) {
throw new InvalidArgumentException(\sprintf('"%s" is not a "BackedEnum" class.', $cases));
}
$cases = $cases::cases();
} else {
$class = null;
foreach ($cases as $case) {
if (!$case instanceof \BackedEnum) {
throw new InvalidArgumentException(\sprintf('Case must be a "BackedEnum" instance, "%s" given.', get_debug_type($case)));
}
$class ??= $case::class;
if (!$case instanceof $class) {
throw new InvalidArgumentException(\sprintf('"%s::%s" is not a case of "%s".', get_debug_type($case), $case->name, $class));
}
}
}View on GitHub (pinned to 83fa223250)