{"record":{"id":"935607010faa81ec","repo":"colinhacks/zod","slug":"async-refinement-encountered-during-synchronous-pa","errorCode":null,"errorMessage":"Async refinement encountered during synchronous parse operation. Use .parseAsync instead.","messagePattern":"Async refinement encountered during synchronous parse operation\\. Use \\.parseAsync instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v3/types.ts","lineNumber":4380,"sourceCode":"        const result = this._def.schema._parseSync({\n          data: processed,\n          path: ctx.path,\n          parent: ctx,\n        });\n        if (result.status === \"aborted\") return INVALID;\n        if (result.status === \"dirty\") return DIRTY(result.value);\n        if (status.value === \"dirty\") return DIRTY(result.value);\n        return result;\n      }\n    }\n    if (effect.type === \"refinement\") {\n      const executeRefinement = (acc: unknown): any => {\n        const result = effect.refinement(acc, checkCtx);\n        if (ctx.common.async) {\n          return Promise.resolve(result);\n        }\n        if (result instanceof Promise) {\n          throw new Error(\"Async refinement encountered during synchronous parse operation. Use .parseAsync instead.\");\n        }\n        return acc;\n      };\n\n      if (ctx.common.async === false) {\n        const inner = this._def.schema._parseSync({\n          data: ctx.data,\n          path: ctx.path,\n          parent: ctx,\n        });\n        if (inner.status === \"aborted\") return INVALID;\n        if (inner.status === \"dirty\") status.dirty();\n\n        // return value is ignored\n        executeRefinement(inner.value);\n        return { status: status.value, value: inner.value };\n      } else {\n        return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {","sourceCodeStart":4362,"sourceCodeEnd":4398,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v3/types.ts#L4362-L4398","documentation":"Thrown at packages/zod/src/v3/types.ts:4380 during a synchronous parse when a refinement's return value is a Promise. Zod detects (result instanceof Promise) inside the sync branch of the refinement effect and aborts, because awaiting that Promise would require the async parser. The error message names the exact escape hatch: switch to .parseAsync().","triggerScenarios":"Defining `z.string().refine(async (v) => await isValid(v))` and then parsing with `.parse()` or `.safeParse()` (the sync path). The refine callback returns a Promise, the sync branch in executeRefinement sees it, and throws.","commonSituations":"Adding a DB/HTTP-backed refinement to a schema that callers parse synchronously; mixing sync and async refinements in one schema; refactoring a refinement from sync to async without updating call sites; shared schema modules used by both sync and async callers.","solutions":["Switch every consumer of the schema to `await schema.parseAsync(data)` / `await schema.safeParseAsync(data)`.","If a consumer must stay sync, rewrite the refinement to be synchronous (precompute the lookup, or cache the result).","Split the schema: keep a sync schema for fast checks and run the async refinement only where you can await.","Audit all .refine/.superRefine callbacks on the schema for a returned Promise."],"exampleFix":"// before\nconst schema = z.object({\n  email: z.string().refine(async (v) => !(await isBlacklisted(v))),\n});\nschema.parse(input); // throws: Async refinement encountered...\n\n// after\nawait schema.parseAsync(input);","handlingStrategy":"validation","validationCode":"import { ZodType, ZodFirstPartyTypeKind } from 'zod';\n\nfunction findAsyncRefinements(schema: ZodType, path: string[] = []): string[] {\n  const def = (schema as any)._def;\n  if (!def) return [];\n  if (def.typeName === ZodFirstPartyTypeKind.ZodEffects && def.effect?.type === 'refinement') {\n    const src = def.effect.refinement?.toString() ?? '';\n    if (/\\basync\\b/.test(src)) return [path.join('.') || '(root)'];\n    return findAsyncRefinements(def.schema, path);\n  }\n  return [];\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Switch all consumers of an async-refined schema to .parseAsync()/.safeParseAsync().","Run a repo-wide grep for `.refine(async` and `.superRefine(async` when adding async checks.","Keep sync schemas sync: do I/O before parse and pass results in as data.","Document in module JSDoc which schemas require the async parse path."],"tags":["async","refine","parse","sync","effects"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}