colinhacks/zod · error · Error

Synchronous parse encountered promise.

Error message

Synchronous parse encountered promise.

What it means

Thrown by _parseSync at packages/zod/src/v3/types.ts:213 when a schema's internal _parse returns a Promise (an async result) but a synchronous code path demanded a value now. Zod's sync parser cannot await promises, so it aborts rather than silently returning garbage. The typical upstream cause is a schema containing an async refinement or async transform being driven through a sync API like .parse(), .safeParse(), or .spa() in v3.

Solutions

  1. Switch the call site to the async API: `await schema.parseAsync(data)` or `await schema.safeParseAsync(data)`.
  2. If the call site must stay sync, replace the async refine/transform with a synchronous check.
  3. Audit every `.refine()` and `.transform()` on the schema to confirm none returns a Promise.
  4. If you control the custom ZodType, ensure _parse returns a synchronous result when parsed synchronously, or only expose the async path.

Example fix

// before
const schema = z.string().refine(async (v) => await checkDb(v));
schema.parse(input); // throws: Synchronous parse encountered promise.

// after
const schema = z.string().refine(async (v) => await checkDb(v));
await schema.parseAsync(input);
Defensive patterns

Strategy: validation

Validate before calling

import { ZodType, ZodFirstPartyTypeKind } from 'zod';

// Best-effort check: walk the schema definition for refine/transform effects.
function hasAsyncEffect(schema: ZodType): boolean {
  const def = (schema as any)._def;
  if (!def) return false;
  if (def.typeName === ZodFirstPartyTypeKind.ZodEffects) {
    const eff = def.effect;
    if (eff?.type === 'refinement' || eff?.type === 'transform') {
      // heuristic: function source contains 'async'
      const src = eff.refinement?.toString() || eff.transform?.toString() || '';
      if (/\basync\b/.test(src)) return true;
    }
    return hasAsyncEffect(def.schema);
  }
  // recurse into common containers as needed
  return false;
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling `.parse()` or `.safeParse()` (synchronous) on a schema that has a `.refine(async ...)` or `.transform(async ...)` where the inner function returns a Promise. Also reached when a custom ZodType subclass overrides _parse to return a Promise but is then parsed via _parseSync.

Common situations: Writing a refinement that hits a database or HTTP endpoint and returns a Promise, then forgetting to switch the call site to .parseAsync(); adding an async transform during refactor without updating callers; library code that calls .parse() generically on user-supplied schemas that may be async.

Related errors


AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11). Data as JSON: /api/errors/566e941a4df632f0. Report an issue: GitHub.

Appendix: 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 2d90846af9)