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 at packages/zod/src/v3/types.ts:4421 during a synchronous parse when a transform's return value is a Promise. In the sync branch of the transform effect, Zod checks `if (result instanceof Promise)` and throws, because it cannot await the result inline. The message points to the remedy: use .parseAsync().
Solutions
- Move the call site to `await schema.parseAsync(data)` / `await schema.safeParseAsync(data)`.
- If the call site must stay sync, replace the async transform with a synchronous one (do the I/O before parse, pass the result in).
- Restructure so the async work happens outside the schema and the transform only reshapes already-fetched data synchronously.
- Audit every .transform() on the schema for a returned Promise.
Example fix
// before const schema = z .string() .transform(async (id) => await db.find(id)); schema.parse(input); // throws: Asynchronous transform encountered... // after await schema.parseAsync(input);
Defensive patterns
Strategy: validation
Validate before calling
import { ZodType, ZodFirstPartyTypeKind } from 'zod';
function findAsyncTransforms(schema: ZodType, path: string[] = []): string[] {
const def = (schema as any)._def;
if (!def) return [];
if (def.typeName === ZodFirstPartyTypeKind.ZodEffects && def.effect?.type === 'transform') {
const src = def.effect.transform?.toString() ?? '';
if (/\basync\b/.test(src)) return [path.join('.') || '(root)'];
return findAsyncTransforms(def.schema, path);
}
return [];
} Type guard
null
Try / catch
null
Prevention
- Switch callers to .parseAsync()/.safeParseAsync() whenever a transform returns a Promise.
- Do I/O before parse and let the transform only reshape already-fetched data synchronously.
- Grep for `.transform(async` when introducing async work in a schema pipeline.
- Document which exported schemas are async-only.
When it happens
Trigger: Defining `z.string().transform(async (v) => await fetchDetails(v))` and parsing through `.parse()` or `.safeParse()` (sync). The transform returns a Promise, triggering the guard.
Common situations: Writing a transform that does I/O (fetch, DB, file read) and forgetting that transforms default to the sync parse path; converting a preprocess/transform pipeline to async without updating callers; library code that calls .parse() on user schemas that may contain async transforms.
Related errors
- Async refinement encountered during synchronous parse…
- Synchronous parse encountered promise.
- Async schemas not supported in object keys currently
- Transforms cannot be represented in JSON Schema
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/fef3ed001efd6eb4.
Report an issue: GitHub.
Appendix: 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 2d90846af9)