colinhacks/zod · error · Error

This schema contains multiple valid literal values. Use `.va

Error message

This schema contains multiple valid literal values. Use `.values` instead.

What it means

In Zod v4 `z.literal()` accepts an array of values, producing a multi-value literal schema whose `.values` is a Set (schemas.ts:2016). The legacy single-value `.value` getter (schemas.ts:2017) throws when `def.values.length > 1` because a single value is ambiguous. The getter exists for backwards compatibility and explicitly redirects users to `.values`.

Source

Thrown at packages/zod/src/v4/classic/schemas.ts:2020

// ZodLiteral
export interface ZodLiteral<T extends util.Literal = util.Literal>
  extends _ZodType<core.$ZodLiteralInternals<T>>,
    core.$ZodLiteral<T> {
  "~standard": ZodStandardSchemaWithJSON<this>;
  values: Set<T>;
  /** @legacy Use `.values` instead. Accessing this property will throw an error if the literal accepts multiple values. */
  value: T;
}
export const ZodLiteral: core.$constructor<ZodLiteral> = /*@__PURE__*/ core.$constructor("ZodLiteral", (inst, def) => {
  core.$ZodLiteral.init(inst, def);
  ZodType.init(inst, def);
  inst._zod.processJSONSchema = (ctx, json, params) => processors.literalProcessor(inst, ctx, json, params);
  inst.values = new Set(def.values);
  Object.defineProperty(inst, "value", {
    get() {
      if (def.values.length > 1) {
        throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
      }
      return def.values[0];
    },
  });
});

export function literal<const T extends ReadonlyArray<util.Literal>>(
  value: T,
  params?: string | core.$ZodLiteralParams
): ZodLiteral<T[number]>;
export function literal<const T extends util.Literal>(
  value: T,
  params?: string | core.$ZodLiteralParams
): ZodLiteral<T>;
export function literal(value: any, params: any) {
  return new ZodLiteral({
    type: "literal",
    values: Array.isArray(value) ? value : [value],

View on GitHub (pinned to 912f0f51b0)

Solutions

  1. Switch the read from `.value` to `.values` (a Set); use `[...schema.values][0]` if you specifically need one.
  2. If a single value is semantically required, construct with a scalar: `z.literal("a")` so `.value` stays valid.
  3. Guard the access: `if (schema.values.size === 1) { schema.value } else { ... }`.

Example fix

// before
const s = z.literal(["a", "b"]);
const v = s.value; // throws
// after
const s = z.literal(["a", "b"]);
const v = s.values; // Set { "a", "b" }
Defensive patterns

Strategy: type-guard

Type guard

import { z } from "zod";

function isSingleValueLiteral(s: z.ZodLiteral<any>): boolean {
  return s.values.size === 1;
}

const v = isSingleValueLiteral(schema) ? schema.value : schema.values;

Prevention

When it happens

Trigger: Constructing `z.literal(["a", "b"])` (or any array with 2+ entries) then reading `.value` on the resulting schema. Also reachable by merging/concatenating literals into a multi-value one.

Common situations: Migrating Zod v3 code that read `.value` on literals; building a literal from a dynamically-sized array that happens to contain more than one element; refactoring a single-value literal into a union/multi form without updating `.value` accesses.

Related errors


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