colinhacks/zod · error · Error

Cannot create literal schema with no valid values

Error message

Cannot create literal schema with no valid values

What it means

Thrown in the `$ZodLiteral` constructor when `def.values` is empty. A literal schema must accept at least one concrete value; `z.literal()` with no argument, or `z.literal([])` (an empty array spread into values), produces an empty set and cannot match anything, so construction fails immediately at definition time.

Source

Thrown at packages/zod/src/v4/core/schemas.ts:3279

}

export interface $ZodLiteralInternals<T extends util.Literal = util.Literal> extends $ZodTypeInternals<T, T> {
  def: $ZodLiteralDef<T>;
  values: Set<T>;
  pattern: RegExp;
  isst: errors.$ZodIssueInvalidValue;
}

export interface $ZodLiteral<T extends util.Literal = util.Literal> extends $ZodType {
  _zod: $ZodLiteralInternals<T>;
}

export const $ZodLiteral: core.$constructor<$ZodLiteral> = /*@__PURE__*/ core.$constructor(
  "$ZodLiteral",
  (inst, def) => {
    $ZodType.init(inst, def);
    if (def.values.length === 0) {
      throw new Error("Cannot create literal schema with no valid values");
    }

    const values = new Set<util.Literal>(def.values);
    inst._zod.values = values;
    inst._zod.pattern = new RegExp(
      `^(${def.values

        .map((o) => (typeof o === "string" ? util.escapeRegex(o) : o ? util.escapeRegex(o.toString()) : String(o)))
        .join("|")})$`
    );

    inst._zod.parse = (payload, _ctx) => {
      const input = payload.value;
      if (values.has(input)) {
        return payload;
      }
      payload.issues.push({
        code: "invalid_value",

View on GitHub (pinned to 912f0f51b0)

Solutions

  1. Pass at least one literal value to `z.literal(...)`, e.g. `z.literal('active')` or `z.literal(['a','b'])`.
  2. If the value list is dynamic, guard it: only construct `z.literal(values)` when `values.length > 0`, otherwise fall back to `z.never()` or `z.any()` depending on intent.
  3. Check the upstream data source feeding the literal list to ensure it is non-empty.

Example fix

// before
const allowed: string[] = [];
const S = z.literal(allowed); // throws

// after
const allowed: string[] = [];
const S = allowed.length > 0 ? z.literal(allowed) : z.never();
Defensive patterns

Strategy: validation

Validate before calling

function safeLiteral(values) {
  if (!values || (Array.isArray(values) ? values.length === 0 : values === undefined)) {
    throw new Error('z.literal requires at least one value');
  }
  return z.literal(values);
}

Type guard

function hasLiteralValues(values): boolean {
  return Array.isArray(values) ? values.length > 0 : values !== undefined && values !== null;
}

Try / catch

try {
  const S = z.literal(dynamicValues);
} catch (e) {
  if (e instanceof Error && e.message === 'Cannot create literal schema with no valid values') {
    // fall back to z.never() or ensure the source list is populated
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `z.literal()` with no arguments; `z.literal([])`; programmatically building `z.literal([...someArray])` where `someArray` is empty; spreading a dynamic list into `z.literal(...)` that turns out empty.

Common situations: Generating schemas from configuration/JSON where the allowed-value list may be empty; refactoring a list of literals and accidentally passing an empty array; type-loose wrappers around `z.literal`.

Related errors


AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03). Data as JSON: /data/errors/759c2140359c9e92.json. Report an issue: GitHub.