colinhacks/zod · error · Error
Invalid template literal part: ${part}
Error message
Invalid template literal part: ${part} What it means
Thrown in `$ZodTemplateLiteral` when a part is neither a Zod schema object (no `_zod`), nor `null`, nor a primitive (string/number/boolean/undefined per `util.primitiveTypes`). Template literal parts must be primitives (interpolated literally) or string-patterned Zod schemas; anything else is rejected.
Source
Thrown at packages/zod/src/v4/core/schemas.ts:4311
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) => {
if (typeof payload.value !== "string") {
payload.issues.push({
input: payload.value,
inst,
expected: "string",
code: "invalid_type",
});
return payload;
}
inst._zod.pattern.lastIndex = 0;
if (!inst._zod.pattern.test(payload.value)) {View on GitHub (pinned to 912f0f51b0)
Solutions
- Only pass primitives (string/number/boolean) or Zod schemas as template parts.
- If you need a dynamic object's value, extract a primitive field (e.g. `obj.id`) or stringify it into a `z.literal(String(obj))`.
- Filter/map the parts array before passing it to ensure every element is a primitive or schema.
Example fix
// before
const T = z.templateLiteral([z.literal('u:'), { id: 5 }]);
// after
const T = z.templateLiteral([z.literal('u:'), z.literal('5')]);
// or build the literal from a primitive string:
const T2 = z.templateLiteral(['u:', String(5)]); Defensive patterns
Strategy: type-guard
Validate before calling
const PRIMS = new Set(['string','number','boolean','bigint','symbol','undefined']);
function isValidTemplatePart(p) {
if (p === null) return true;
if (PRIMS.has(typeof p)) return true;
if (typeof p === 'object' && p !== null && p._zod) return true;
return false;
}
parts.forEach((p) => { if (!isValidTemplatePart(p)) throw new Error('invalid template part'); }); Type guard
const PRIMS = new Set(['string','number','boolean','bigint','symbol','undefined']);
function isValidTemplatePart(p): boolean {
if (p === null) return true;
if (PRIMS.has(typeof p)) return true;
return typeof p === 'object' && p !== null && !!p._zod;
} Try / catch
try {
const T = z.templateLiteral(parts);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Invalid template literal part:')) {
// filter parts to primitives/schemas before rebuilding
}
throw e;
} Prevention
- Map/filter mixed input arrays to primitives or schemas before passing to z.templateLiteral.
- Never pass plain objects, Dates, or class instances as template parts.
- Stringify non-primitive values into z.literal(...) explicitly.
When it happens
Trigger: Passing a plain JS object, an array, a `Date`, a `Symbol`, or any non-schema non-primitive as a part to `z.templateLiteral([...])`. E.g. `z.templateLiteral([{ foo: 1 }])`.
Common situations: Passing config objects or class instances expecting them to be stringified; spreading an array of mixed parts that includes objects.
Related errors
- Invalid discriminated union option at index "${def.options.i
- Invalid discriminated union option at index "${def.options.i
- Duplicate discriminator value "${String(v)}"
- Cannot create literal schema with no valid values
- Invalid template literal part, no pattern found: ${[...(part
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/489de54e9ccf86a3.json.
Report an issue: GitHub.