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
- Add a backing type to the enum: `enum Status: string { ... }` and give each case an explicit value, e.g. `case Active = 'active';`
- If the enum cannot be changed, create a new backed enum for persistence and map to it in the entity
- 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
- Always declare DB-backed enums as `enum X: string` or `enum X: int` with explicit case values
- Check is_subclass_of($class, BackedEnum::class) when wiring types dynamically
- Keep unit enums separate from persistence enums
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
- Unable to use ` ` for type ` `. .
- driver
- The `$when` argument must be a non-empty array
- When using an array for the `$when` argument, the `$type`…
- When using a non-array value for the `$when` argument, the…
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)