colinhacks/zod · error · Error
Asynchronous transform encountered during synchronous parse
Error message
Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.
What it means
Thrown inside ZodEffects when an effect of type 'transform' returns a Promise during a synchronous parse. Transforms that resolve asynchronously cannot be applied synchronously, so zod refuses rather than producing a Promise-typed output in a sync slot.
Source
Thrown at packages/zod/src/v3/types.ts:4421
return { status: status.value, value: inner.value };
});
});
}
}
if (effect.type === "transform") {
if (ctx.common.async === false) {
const base = this._def.schema._parseSync({
data: ctx.data,
path: ctx.path,
parent: ctx,
});
if (!isValid(base)) return INVALID;
const result = effect.transform(base.value, checkCtx);
if (result instanceof Promise) {
throw new Error(
`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`
);
}
return { status: status.value, value: result };
} else {
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
if (!isValid(base)) return INVALID;
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
status: status.value,
value: result,
}));
});
}
}
util.assertNever(effect);View on GitHub (pinned to 912f0f51b0)
Solutions
- Use `.parseAsync` / `.spa` at the call site.
- Make the transform synchronous if a sync result is required (precompute, look up in-memory).
- Split the schema so the async transform lives in a separate async-validated schema.
Example fix
// before const schema = z.string().transform(async (id) => await fetchUser(id)); schema.parse(id); // throws // after const user = await schema.parseAsync(id);
Defensive patterns
Strategy: retry
Try / catch
try { schema.parse(data); }
catch (e) {
if (e instanceof Error && /Asynchronous transform|Use \.parseAsync/.test(e.message)) {
return await schema.parseAsync(data);
}
throw e;
} Prevention
- Prefer sync transforms unless you genuinely need I/O.
- If a transform is async, route every consumer through parseAsync/spa.
- Add a unit test that exercises the async path to catch sync usage early.
When it happens
Trigger: Using `.transform(async (val) => ...)` (or a transform that incidentally returns a thenable) and invoking `.parse()` / `.safeParse()`. Nested transforms inside an object/array can trigger it too.
Common situations: Converting a transform that fetches related data into async; using `.transform(async ...)` with `.refine` chaining in a sync handler; tests calling the sync API.
Related errors
- Async refinement encountered during synchronous parse operat
- Synchronous parse encountered promise.
- 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/fef3ed001efd6eb4.json.
Report an issue: GitHub.