{"record":{"id":"d67f720d670fe524","repo":"colinhacks/zod","slug":"async-schemas-not-supported-in-object-keys-current","errorCode":null,"errorMessage":"Async schemas not supported in object keys currently","messagePattern":"Async schemas not supported in object keys currently","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/schemas.ts","lineNumber":2920,"sourceCode":"\n        input,\n        inst,\n      });\n      return payload;\n    }\n\n    const proms: Promise<any>[] = [];\n\n    const values = def.keyType._zod.values;\n    if (values) {\n      payload.value = {};\n      const recordKeys = new Set<string | symbol>();\n      for (const key of values) {\n        if (typeof key === \"string\" || typeof key === \"number\" || typeof key === \"symbol\") {\n          recordKeys.add(typeof key === \"number\" ? key.toString() : key);\n          const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);\n          if (keyResult instanceof Promise) {\n            throw new Error(\"Async schemas not supported in object keys currently\");\n          }\n          if (keyResult.issues.length) {\n            payload.issues.push({\n              code: \"invalid_key\",\n              origin: \"record\",\n              issues: keyResult.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())),\n              input: key,\n              path: [key],\n              inst,\n            });\n            continue;\n          }\n          const outKey = keyResult.value as PropertyKey;\n          const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);\n\n          if (result instanceof Promise) {\n            proms.push(\n              result.then((result) => {","sourceCodeStart":2902,"sourceCodeEnd":2938,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/schemas.ts#L2902-L2938","documentation":"Thrown during record parsing on the fast path that iterates def.keyType._zod.values, when running the key schema on a candidate key returns a Promise. Object keys must be validated synchronously because they are enumerated eagerly to build the output object; an async key schema (e.g. one containing z.string().refine(async ...) or a transform that returns a promise) cannot be awaited inline and is rejected. The check is `if (keyResult instanceof Promise)`.","triggerScenarios":"Defining z.record(keyType, valueType) where keyType is or contains an async refinement or transform — e.g. z.string().refine(async () => ...), z.string().transform(async ...), or a pipe that yields a promise. Parsing any input against such a record triggers the throw on the first value-key iteration.","commonSituations":"Using a database-backed validator on the key schema; copying a value-side refine (that happens to be async) onto the key side; piping the key through an async preprocess; mixing z.record() with schemas designed for async value validation.","solutions":["Remove all async refinements/transforms from the record's key schema.","Replace async validation with a synchronous approximation (regex, .refine without async, .regex).","If async key validation is truly required, validate keys manually before construction instead of via the record's keyType."],"exampleFix":"// before\nconst R = z.record(\n  z.string().refine(async (k) => await isAllowed(k)),\n  z.number()\n);\n// after\nconst R = z.record(\n  z.string().refine((k) => ALLOWED.has(k)),\n  z.number()\n);","handlingStrategy":"type-guard","validationCode":"function isSyncKeySchema(keyType: z.ZodType): boolean {\n  // Run the schema on a sample value and confirm it doesn't return a Promise\n  const r = (keyType as any)._zod.run({ value: \"__probe__\", issues: [] }, undefined);\n  return !(r instanceof Promise);\n}","typeGuard":"function isSyncKeySchema(keyType: z.ZodType): boolean {\n  const r = (keyType as any)._zod.run({ value: \"__probe__\", issues: [] }, undefined);\n  return !(r instanceof Promise);\n}","tryCatchPattern":null,"preventionTips":["Never use async refinements/transforms on a record's key schema.","Keep key schemas to sync primitives (z.string(), z.number(), z.literal(), z.enum()).","Do async checks outside the record, then construct it from filtered input."],"tags":["record","async","object-keys","runtime"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}