cakephp/cakephp · error · DatabaseException

Unable to use enum ` ` for type ` `, must be a backed enum.

Error message

Unable to use enum `%s` for type `%s`, must be a backed enum.

What it means

EnumType requires the associated PHP enum to be a backed enum (one declared with a string or int backing type, e.g. `enum Status: string`). This DatabaseException is thrown in the constructor when ReflectionEnum::getBackingType() returns null, i.e. the class is a valid enum but a pure/unit enum without backing values. Backed values are required to store the enum in a database column.

Solutions

  1. Add a backing type to the enum: `enum Status: string { ... }` and give each case an explicit value, e.g. `case Active = 'active';`
  2. If the enum cannot be changed, create a new backed enum for persistence and map to it in the entity
  3. Use a non-EnumType (e.g. StringType) plus manual conversion if a unit enum must stay unit

Example fix

// before
enum Status { case Active; case Inactive; }
// after
enum Status: string { case Active = 'active'; case Inactive = 'inactive'; }
Defensive patterns

Strategy: validation

Validate before calling

if (enum_exists($class) && !(new \ReflectionEnum($class))->getBackingType()) { throw new \LogicException("{$class} must be a backed enum"); }

Type guard

function isBackedEnumClass(string $class): bool { return enum_exists($class) && is_subclass_of($class, \BackedEnum::class); }

Try / catch

try { $type = new EnumType('status', $class); } catch (\Cake\Database\DatabaseException $e) { // fail fast at config time, not at save time }

Prevention

When it happens

Trigger: Constructing EnumType with a unit enum such as `enum Status { case Active; case Inactive; }` (no `: string` / `: int` after the name).

Common situations: Migrating legacy unit enums to DB types; copying an enum defined for in-memory use only and wiring it to EnumType without adding a backing type; third-party enum classes that are not backed.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12). Data as JSON: /api/errors/32d3ea9d51e6a0ab. Report an issue: GitHub.

Appendix: source

Thrown at src/Database/Type/EnumType.php:76

        string $enumClassName,
    ) {
        parent::__construct($name);
        $this->enumClassName = $enumClassName;

        try {
            $reflectionEnum = new ReflectionEnum($enumClassName);
        } catch (ReflectionException $e) {
            throw new DatabaseException(sprintf(
                'Unable to use `%s` for type `%s`. %s.',
                $enumClassName,
                $name,
                $e->getMessage(),
            ));
        }

        $namedType = $reflectionEnum->getBackingType();
        if ($namedType === null) {
            throw new DatabaseException(
                sprintf('Unable to use enum `%s` for type `%s`, must be a backed enum.', $enumClassName, $name),
            );
        }

        $this->backingType = (string)$namedType;
    }

    /**
     * Convert enum instances into the database format.
     *
     * @param mixed $value The value to convert.
     * @param \Cake\Database\Driver $driver The driver instance to convert with.
     * @return string|int|null
     * @throws \InvalidArgumentException When the given value is not a valid value for the associated enum
     */
    public function toDatabase(mixed $value, Driver $driver): string|int|null
    {
        if ($value === null) {

View on GitHub (pinned to 1128eba9b0)