colinhacks/zod · error · Error

Invalid template literal part, no pattern found

Error message

Invalid template literal part, no pattern found: ${[...(part as any)._zod.traits].shift()}

What it means

Thrown by the $ZodTemplateLiteral constructor while iterating def.parts when a part is an object (treated as a Zod schema) but has no _zod.pattern. Template literals build a single regex by concatenating each part's pattern; a schema part without a pattern (e.g. z.any(), z.unknown(), z.never(), z.void(), or a non-string schema that never publishes a pattern) cannot contribute a regex fragment. The message prints the first trait of the offending part to help identify its type.

Solutions

  1. Use only string-pattern-producing schemas in the template: z.string(), z.number(), z.literal(), z.uuid(), z.date(), z.enum(), or nested z.template`...`.
  2. Replace z.any()/z.unknown() with z.string() or another patterned primitive.
  3. For custom schemas, assign inst._zod.pattern in the constructor so the template can consume it.
  4. If a non-patterned schema is essential, pre-compute its string fragment and inline it as a plain string part.

Example fix

// before
const T = z.template`${z.any()}-${z.number()}`;
// after
const T = z.template`${z.string()}-${z.number()}`;
Defensive patterns

Strategy: type-guard

Validate before calling

function isPatterned(part: unknown): boolean {
  return typeof part === "object" && part !== null && !!(part as any)?._zod?.pattern;
}

Type guard

function isPatterned(part: unknown): boolean {
  return typeof part === "object" && part !== null && !!(part as any)?._zod?.pattern;
}

Prevention

When it happens

Trigger: Calling z.template`${z.any()}`, z.template`${z.unknown()}`, or embedding a schema that does not expose _zod.pattern (transforms whose output has no pattern, some object/array schemas, or custom schemas missing a pattern).

Common situations: Composing a template from user-supplied schemas without checking they are pattern-bearing; upgrading a schema in the template to one without a pattern; using z.lazy() or z.custom() whose resolved schema lacks a pattern; passing a non-string primitive-wrapper by mistake.

Related errors


AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11). Data as JSON: /api/errors/cc413bd95ec4ac03. Report an issue: GitHub.

Appendix: source

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

export type $PartsToTemplateLiteral<Parts extends $ZodTemplateLiteralPart[]> = [] extends Parts
  ? ``
  : Parts extends [...infer Rest, infer Last extends $ZodTemplateLiteralPart]
    ? Rest extends $ZodTemplateLiteralPart[]
      ? AppendToTemplateLiteral<$PartsToTemplateLiteral<Rest>, Last>
      : never
    : never;

export const $ZodTemplateLiteral: core.$constructor<$ZodTemplateLiteral> = /*@__PURE__*/ core.$constructor(
  "$ZodTemplateLiteral",
  (inst, def) => {
    $ZodType.init(inst, def);
    const regexParts: string[] = [];
    for (const part of def.parts) {
      if (typeof part === "object" && part !== null) {
        // is Zod schema
        if (!part._zod.pattern) {
          // if (!source)
          throw new Error(`Invalid template literal part, no pattern found: ${[...(part as any)._zod.traits].shift()}`);
        }

        const source = part._zod.pattern instanceof RegExp ? part._zod.pattern.source : part._zod.pattern;

        if (!source) throw new Error(`Invalid template literal part: ${part._zod.traits}`);

        const start = source.startsWith("^") ? 1 : 0;
        const end = source.endsWith("$") ? source.length - 1 : source.length;
        regexParts.push(source.slice(start, end));
      } else if (part === null || util.primitiveTypes.has(typeof part)) {
        regexParts.push(util.escapeRegex(`${part}`));
      } else {
        throw new Error(`Invalid template literal part: ${part}`);
      }
    }
    inst._zod.pattern = new RegExp(`^${regexParts.join("")}$`);

    inst._zod.parse = (payload, _ctx) => {

View on GitHub (pinned to 2d90846af9)