colinhacks/zod · error · Error
Key not found in enum
Error message
Key ${value} not found in enum What it means
Thrown by ZodEnum.prototype.extract(values) when one of the requested keys is not present in the enum's entries map. extract() builds a new enum containing only the listed keys, so every supplied value must already be an existing enum key.
Solutions
- Ensure every string passed to extract() is a literal key of the original enum; check the enum's .enum or .options first.
- If filtering by value rather than key, map values back to keys or use z.enum on the value array directly.
- Filter the requested list through Object.keys(enum.entries) before calling extract() so unknown keys are dropped instead of throwing.
Example fix
// before (throws — 'PURPLE' is not a key) const Colors = z.enum(['RED', 'GREEN', 'BLUE']); const Warm = Colors.extract(['RED', 'PURPLE']); // after const Warm = Colors.extract(['RED', 'BLUE']);
Defensive patterns
Strategy: validation
Validate before calling
function safeExtract(enumSchema, keys) {
const valid = new Set(Object.keys(enumSchema.enum));
const unknown = keys.filter((k) => !valid.has(k));
if (unknown.length) {
throw new Error(`Unknown enum keys: ${unknown.join(', ')}`);
}
return enumSchema.extract(keys);
} Type guard
function isEnumKey(enumSchema, key) {
return Object.prototype.hasOwnProperty.call(enumSchema.enum, key);
} Try / catch
try {
const Sub = MyEnum.extract(requestedKeys);
} catch (e) {
if (e.message.includes('not found in enum')) {
// log the offending key and degrade gracefully
return null;
}
throw e;
} Prevention
- Derive extract() argument lists from Object.keys(enum.enum) at the call site so they can never drift.
- Add compile-time checks (e.g. `satisfies keyof typeof MyEnum`) for literal arrays.
- Unit-test extract() call sites whenever the source enum changes.
When it happens
Trigger: Calling myEnum.extract(['RED','PURPLE']) when 'PURPLE' was never defined. Passing the enum *values* instead of the enum *keys* to extract(). Renaming a key in the source enum but forgetting to update an extract() call elsewhere.
Common situations: Refactoring an enum and leaving stale extract() call sites. Confusing key vs value semantics (in z.enum they coincide for string enums, but native enums with numeric values or renamed keys diverge). Splitting a shared enum into sub-enums at multiple call sites.
Related errors
- This schema contains multiple valid literal values. Use…
- A discriminator value for key
- Can't use "invalid_type_error" or "required_error" in…
- Cannot create literal schema with no valid values
- Cannot specify both `message` and `error` params
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/29d0494a8ef5b8e5.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/classic/schemas.ts:1946
params?: string | core.$ZodEnumParams
): ZodEnum<util.Flatten<Omit<T, U[number]>>>;
}
export const ZodEnum: core.$constructor<ZodEnum> = /*@__PURE__*/ core.$constructor("ZodEnum", (inst, def) => {
core.$ZodEnum.init(inst, def);
ZodType.init(inst, def);
inst._zod.processJSONSchema = (ctx, json, params) => processors.enumProcessor(inst, ctx, json, params);
inst.enum = def.entries;
inst.options = Object.values(def.entries);
const keys = new Set(Object.keys(def.entries));
inst.extract = (values, params) => {
const newEntries: Record<string, any> = {};
for (const value of values) {
if (keys.has(value)) {
newEntries[value] = def.entries[value];
} else throw new Error(`Key ${value} not found in enum`);
}
return new ZodEnum({
...def,
checks: [],
...util.normalizeParams(params),
entries: newEntries,
}) as any;
};
inst.exclude = (values, params) => {
const newEntries: Record<string, any> = { ...def.entries };
for (const value of values) {
if (keys.has(value)) {
delete newEntries[value];
} else throw new Error(`Key ${value} not found in enum`);
}
return new ZodEnum({
...def,View on GitHub (pinned to 2d90846af9)