colinhacks/zod · error · Error

Set cannot be represented in JSON Schema

Error message

Set cannot be represented in JSON Schema

What it means

JSON Schema arrays are ordered and can carry duplicates, so a `Set` (unique, unordered) has no faithful representation; `setProcessor` (json-schema-processors.ts:268) throws for `z.set(valueType)` when `ctx.unrepresentable === "throw"` (default).

Source

Thrown at packages/zod/src/v4/core/json-schema-processors.ts:270

    throw new Error("Function types cannot be represented in JSON Schema");
  }
};

export const transformProcessor: Processor<schemas.$ZodTransform> = (_schema, ctx, _json, _params) => {
  if (ctx.unrepresentable === "throw") {
    throw new Error("Transforms cannot be represented in JSON Schema");
  }
};

export const mapProcessor: Processor<schemas.$ZodMap> = (_schema, ctx, _json, _params) => {
  if (ctx.unrepresentable === "throw") {
    throw new Error("Map cannot be represented in JSON Schema");
  }
};

export const setProcessor: Processor<schemas.$ZodSet> = (_schema, ctx, _json, _params) => {
  if (ctx.unrepresentable === "throw") {
    throw new Error("Set cannot be represented in JSON Schema");
  }
};

// ==================== COMPOSITE TYPE PROCESSORS ====================

export const arrayProcessor: Processor<schemas.$ZodArray> = (schema, ctx, _json, params) => {
  const json = _json as JSONSchema.ArraySchema;
  const def = schema._zod.def as schemas.$ZodArrayDef;
  const { minimum, maximum } = schema._zod.bag;
  if (typeof minimum === "number") json.minItems = minimum;
  if (typeof maximum === "number") json.maxItems = maximum;

  json.type = "array";
  json.items = process(def.element, ctx as any, {
    ...params,
    path: [...params.path, "items"],
  });
};

View on GitHub (pinned to 912f0f51b0)

Solutions

  1. Pass `{ unrepresentable: "any" }` to emit an empty schema for the set node.
  2. Re-model as `z.array(valueType)` (JSON Schema array); enforce uniqueness at the application layer.
  3. If uniqueness must be visible in the contract, use `z.array(valueType)` plus a `uniqueItems: true` via an override.

Example fix

// before
z.toJSONSchema(z.set(z.string())); // throws
// after
z.toJSONSchema(z.array(z.string())); // -> { type: "array", items: { type: "string" } }
Defensive patterns

Strategy: fallback

Validate before calling

// Model unique collections as arrays in contract schemas.
const contractSchema = z.array(z.string());
const json = z.toJSONSchema(contractSchema);

Type guard

function usesSet(schema: z.ZodType): boolean {
  return schema._zod.traits.has("$ZodSet");
}

Try / catch

try {
  return z.toJSONSchema(schema);
} catch (e) {
  if (e instanceof Error && /cannot be represented in JSON Schema/.test(e.message)) {
    return z.toJSONSchema(schema, { unrepresentable: "any" });
  }
  throw e;
}

Prevention

When it happens

Trigger: `z.toJSONSchema()` over a schema containing `z.set(z.string())`, with default options.

Common situations: Documenting a schema that models unique collections as JS Sets; converting a shared schema that uses Set for deduplication.

Related errors


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