{"record":{"id":"759c2140359c9e92","repo":"colinhacks/zod","slug":"cannot-create-literal-schema-with-no-valid-values","errorCode":null,"errorMessage":"Cannot create literal schema with no valid values","messagePattern":"Cannot create literal schema with no valid values","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/schemas.ts","lineNumber":3296,"sourceCode":"}\n\nexport interface $ZodLiteralInternals<T extends util.Literal = util.Literal> extends $ZodTypeInternals<T, T> {\n  def: $ZodLiteralDef<T>;\n  values: Set<T>;\n  pattern: RegExp;\n  isst: errors.$ZodIssueInvalidValue;\n}\n\nexport interface $ZodLiteral<T extends util.Literal = util.Literal> extends $ZodType {\n  _zod: $ZodLiteralInternals<T>;\n}\n\nexport const $ZodLiteral: core.$constructor<$ZodLiteral> = /*@__PURE__*/ core.$constructor(\n  \"$ZodLiteral\",\n  (inst, def) => {\n    $ZodType.init(inst, def);\n    if (def.values.length === 0) {\n      throw new Error(\"Cannot create literal schema with no valid values\");\n    }\n\n    const values = new Set<util.Literal>(def.values);\n    inst._zod.values = values;\n    inst._zod.pattern = new RegExp(\n      `^(${def.values\n\n        .map((o) => (typeof o === \"string\" ? util.escapeRegex(o) : o ? util.escapeRegex(o.toString()) : String(o)))\n        .join(\"|\")})$`\n    );\n\n    inst._zod.parse = (payload, _ctx) => {\n      const input = payload.value;\n      if (values.has(input)) {\n        return payload;\n      }\n      payload.issues.push({\n        code: \"invalid_value\",","sourceCodeStart":3278,"sourceCodeEnd":3314,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/schemas.ts#L3278-L3314","documentation":"Thrown by the $ZodLiteral constructor when def.values.length === 0. A literal schema must enumerate at least one concrete value to match against; an empty literal set has nothing to accept and would silently reject every input, so construction fails. The public z.literal() API normally guarantees a non-empty array, so this typically surfaces through direct internal construction, a buggy wrapper, or an empty spread.","triggerScenarios":"Calling z.literal([]) or constructing $ZodLiteral with { values: [] }; spreading an empty array into z.literal(...[]); dynamically building a literal from a list that turned out empty; a custom helper that forwards user input to def.values without checking length.","commonSituations":"Generating literal schemas from configuration data (an empty allow-list at config time); refactoring enums to literals and forgetting a fallback; user-driven feature flags that produce no values; off-by-one filters that strip every element.","solutions":["Ensure the values array passed to z.literal() contains at least one entry.","Guard dynamic generators: if (values.length === 0) throw or fall back to z.never()/z.unknown().","Validate configuration upstream so empty allow-lists are caught with a clearer error.","Unit-test the generator against an empty input."],"exampleFix":"// before\nconst L = z.literal([...allowed]); // allowed is []\n// after\nconst L = allowed.length\n  ? z.literal([...allowed])\n  : z.never();","handlingStrategy":"validation","validationCode":"function safeLiteral(values: util.Literal[]) {\n  if (!Array.isArray(values) || values.length === 0) {\n    return z.never();\n  }\n  return z.literal(values);\n}","typeGuard":"function hasValues(values: unknown): values is [unknown, ...unknown[]] {\n  return Array.isArray(values) && values.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate dynamic value lists are non-empty before passing to z.literal().","Provide a fallback (z.never() or z.unknown()) when the list could be empty.","Add a unit test for the empty-list case in any schema factory."],"tags":["literal","schema-construction","validation"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}