{"record":{"id":"1be3cbf40ccb4d27","repo":"jquense/yup","slug":"validation-test-of-type-ctx-type-returned-a","errorCode":null,"errorMessage":"Validation test of type: \"${ctx.type}\" returned a Promise during a synchronous validate. This test will finish after the validate call has returned","messagePattern":"Validation test of type: \"(.+?)\" returned a Promise during a synchronous validate\\. This test will finish after the validate call has returned","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/util/createValidation.ts","lineNumber":155,"sourceCode":"    };\n\n    const handleError = (err: any) => {\n      if (ValidationError.isError(err)) invalid(err);\n      else panic(err);\n    };\n\n    const shouldSkip = skipAbsent && isAbsent(value);\n\n    if (shouldSkip) {\n      return handleResult(true);\n    }\n\n    let result: ReturnType<TestFunction>;\n    try {\n      result = test.call(ctx, value, ctx);\n      if (typeof (result as any)?.then === 'function') {\n        if (options.sync) {\n          throw new Error(\n            `Validation test of type: \"${ctx.type}\" returned a Promise during a synchronous validate. ` +\n              `This test will finish after the validate call has returned`,\n          );\n        }\n        return Promise.resolve(result).then(handleResult, handleError);\n      }\n    } catch (err: any) {\n      handleError(err);\n      return;\n    }\n\n    handleResult(result);\n  }\n\n  validate.OPTIONS = config;\n\n  return validate;\n}","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/jquense/yup/blob/ff31eee8a2b10c938bb3a22544d9e33957a8cf01/src/util/createValidation.ts#L137-L173","documentation":"During synchronous validation (validateSync / sync option), each test function must return a boolean synchronously. If a test returns a Promise (async test), this Error is thrown to warn that the test result will arrive after validateSync has already returned, i.e. its outcome is silently ignored.","triggerScenarios":"Passing an async test (async value => {...} or a function returning a promise, e.g. from an async uniqueness check) to a schema validated with validateSync() or { sync: true }.","commonSituations":"Reusing the same schema with async DB-backed tests for both async and sync validation; using validateSync in a server handler while a test calls fetch/async storage.","solutions":["Use await schema.validate() instead of validateSync() when tests are async","Make the test function synchronous if sync validation is required","Pre-compute async data before validation and pass it in so tests stay sync","Remove the sync flag and switch the whole flow to async validation"],"exampleFix":"// before\nschema.validateSync(value); // test returns a Promise -> throws\n// after\nawait schema.validate(value);","handlingStrategy":"validation","validationCode":"const hasAsyncTest = myTests.some(t => t.constructor.name === 'AsyncFunction');\nif (hasAsyncTest) await schema.validate(value); else value = schema.validateSync(value);","typeGuard":"function isSyncTestResult(r: unknown): r is boolean {\n  return typeof r === 'boolean';\n}\n// or detect async fns up front:\nconst isAsyncFn = (f: Function) => f.constructor.name === 'AsyncFunction';","tryCatchPattern":"try { return schema.validateSync(v); } catch (e) { if (/returned a Promise during a synchronous/.test(e.message)) return await schema.validate(v); throw e; }","preventionTips":["Keep schema tests synchronous if any caller uses validateSync","Search test functions for async/await or Promise returns before enabling sync validation","Default to async validate(); reserve validateSync for known-sync schemas"],"tags":["async","sync-validation","custom-test"],"backgroundTag":"async-test-in-sync-context","analyzedSha":"ff31eee8a2b10c938bb3a22544d9e33957a8cf01","analyzedAt":"2026-08-31T21:51:03.773Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}