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
- 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`...`.
- Replace z.any()/z.unknown() with z.string() or another patterned primitive.
- For custom schemas, assign inst._zod.pattern in the constructor so the template can consume it.
- 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
- Use only pattern-producing schemas (z.string, z.number, z.literal, z.uuid, z.date, z.enum) inside z.template`...`.
- Avoid z.any()/z.unknown()/z.never() in templates.
- For custom schemas, assign inst._zod.pattern in the constructor.
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
- Invalid template literal part
- Invalid template literal part
- Invalid UUID version
- A discriminator value for key
- Can't use "invalid_type_error" or "required_error" in…
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)