{"record":{"id":"566e941a4df632f0","repo":"colinhacks/zod","slug":"synchronous-parse-encountered-promise","errorCode":null,"errorMessage":"Synchronous parse encountered promise.","messagePattern":"Synchronous parse encountered promise\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v3/types.ts","lineNumber":213,"sourceCode":"    return {\n      status: new ParseStatus(),\n      ctx: {\n        common: input.parent.common,\n        data: input.data,\n\n        parsedType: getParsedType(input.data),\n\n        schemaErrorMap: this._def.errorMap,\n        path: input.path,\n        parent: input.parent,\n      },\n    };\n  }\n\n  _parseSync(input: ParseInput): SyncParseReturnType<Output> {\n    const result = this._parse(input);\n    if (isAsync(result)) {\n      throw new Error(\"Synchronous parse encountered promise.\");\n    }\n    return result;\n  }\n\n  _parseAsync(input: ParseInput): AsyncParseReturnType<Output> {\n    const result = this._parse(input);\n    return Promise.resolve(result);\n  }\n\n  parse(data: unknown, params?: util.InexactPartial<ParseParams>): Output {\n    const result = this.safeParse(data, params);\n    if (result.success) return result.data;\n    throw result.error;\n  }\n\n  safeParse(data: unknown, params?: util.InexactPartial<ParseParams>): SafeParseReturnType<Input, Output> {\n    const ctx: ParseContext = {\n      common: {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v3/types.ts#L195-L231","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Switch the call site to the async API: `await schema.parseAsync(data)` or `await schema.safeParseAsync(data)`.","If the call site must stay sync, replace the async refine/transform with a synchronous check.","Audit every `.refine()` and `.transform()` on the schema to confirm none returns a Promise.","If you control the custom ZodType, ensure _parse returns a synchronous result when parsed synchronously, or only expose the async path."],"exampleFix":"// before\nconst schema = z.string().refine(async (v) => await checkDb(v));\nschema.parse(input); // throws: Synchronous parse encountered promise.\n\n// after\nconst schema = z.string().refine(async (v) => await checkDb(v));\nawait schema.parseAsync(input);","handlingStrategy":"validation","validationCode":"import { ZodType, ZodFirstPartyTypeKind } from 'zod';\n\n// Best-effort check: walk the schema definition for refine/transform effects.\nfunction hasAsyncEffect(schema: ZodType): boolean {\n  const def = (schema as any)._def;\n  if (!def) return false;\n  if (def.typeName === ZodFirstPartyTypeKind.ZodEffects) {\n    const eff = def.effect;\n    if (eff?.type === 'refinement' || eff?.type === 'transform') {\n      // heuristic: function source contains 'async'\n      const src = eff.refinement?.toString() || eff.transform?.toString() || '';\n      if (/\\basync\\b/.test(src)) return true;\n    }\n    return hasAsyncEffect(def.schema);\n  }\n  // recurse into common containers as needed\n  return false;\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Treat any .refine(async ...) or .transform(async ...) as a hard signal to switch all callers to .parseAsync().","Run a repo-wide grep for 'async' inside .refine()/​.transform() callbacks when adding the async path.","Document async schemas in their module JSDoc so callers know to await.","Prefer safeParseAsync() in library code that accepts user-supplied schemas."],"tags":["async","parse","refine","transform","sync"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}