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

  1. Use `.parseAsync` / `.spa` at the call site.
  2. Make the transform synchronous if a sync result is required (precompute, look up in-memory).
  3. 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

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


AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03). Data as JSON: /data/errors/fef3ed001efd6eb4.json. Report an issue: GitHub.