colinhacks/zod · error · Error
Synchronous parse encountered promise.
Error message
Synchronous parse encountered promise.
What it means
Thrown by _parseSync when the underlying _parse returns a value flagged as async (a Promise). Synchronous parse paths (`.parse`, `.safeParse`, `.spa` only when awaited-but-sync) cannot await, so zod refuses rather than silently returning `[object Promise]`.
Source
Thrown at packages/zod/src/v3/types.ts:213
return {
status: new ParseStatus(),
ctx: {
common: input.parent.common,
data: input.data,
parsedType: getParsedType(input.data),
schemaErrorMap: this._def.errorMap,
path: input.path,
parent: input.parent,
},
};
}
_parseSync(input: ParseInput): SyncParseReturnType<Output> {
const result = this._parse(input);
if (isAsync(result)) {
throw new Error("Synchronous parse encountered promise.");
}
return result;
}
_parseAsync(input: ParseInput): AsyncParseReturnType<Output> {
const result = this._parse(input);
return Promise.resolve(result);
}
parse(data: unknown, params?: util.InexactPartial<ParseParams>): Output {
const result = this.safeParse(data, params);
if (result.success) return result.data;
throw result.error;
}
safeParse(data: unknown, params?: util.InexactPartial<ParseParams>): SafeParseReturnType<Input, Output> {
const ctx: ParseContext = {
common: {View on GitHub (pinned to 912f0f51b0)
Solutions
- Switch the call site to the async API: `.parseAsync(data)` or `.spa(data)` (returns a Promise).
- If you must stay sync, remove the async refinement/transform or replace it with a sync check.
- Audit nested schemas — the async schema may be a field inside an object or array.
Example fix
// before const schema = z.string().refine(async (v) => await checkDb(v)); schema.parse(value); // throws "Synchronous parse encountered promise." // after await schema.parseAsync(value); // or const res = await schema.spa(value);
Defensive patterns
Strategy: validation
Validate before calling
// Detect async schemas before calling sync parse
function isAsyncSchema(s: z.ZodTypeAny): boolean {
// heuristic: walk _def for ZodEffects with async transform/refine
return /\[z\.async\]|Promise/.test(s.description ?? "") || (s as any)._def?.effect != null;
} Type guard
function canParseSync(s: z.ZodTypeAny): boolean {
// No public flag; safest is to always use parseAsync for schemas that may contain effects.
return true;
} Try / catch
try { schema.parse(data); }
catch (e) {
if (e instanceof Error && /encountered promise|Use \.parseAsync/.test(e.message)) {
return await schema.parseAsync(data);
}
throw e;
} Prevention
- Default to parseAsync/spa whenever a schema uses .refine/.transform with possibly-async callbacks.
- Audit refinements and transforms for `async` keyword before using .parse.
- Keep validation pipelines uniform: pick sync or async per schema and document it.
When it happens
Trigger: Using `.parse()` / `.safeParse()` (sync) on a schema that contains an async refinement (`.refine(async ...)`) or async transform (`.transform(async ...)`), or a schema that nests one.
Common situations: Adding an async validation (e.g. database uniqueness check) to an existing sync pipeline; refactoring a transform to be async without flipping the call site; testing an async schema with a sync assertion.
Related errors
- Async refinement encountered during synchronous parse operat
- Asynchronous transform encountered during synchronous parse
- Can't use "invalid_type_error" or "required_error" in conjun
- A discriminator value for key `${discriminator}` could not b
- Discriminator property ${String(discriminator)} has duplicat
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/566e941a4df632f0.json.
Report an issue: GitHub.