{"record":{"id":"fd9c5800d23fd8f1","repo":"karatelabs/karate","slug":"unhandled-promise-rejection","errorCode":null,"errorMessage":"unhandled promise rejection: ","messagePattern":"unhandled promise rejection: ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/AsyncSupport.java","lineNumber":860,"sourceCode":"     * as handled. The first terminal unhandled rejection fails the eval as a\n     * JS-level error; the rest are logged. Each is reported exactly once.\n     */\n    static void reportUnhandledRejections(Engine engine, AsyncScope scope) {\n        List<JsPromise> tracked = scope.trackedRejections();\n        if (tracked.isEmpty()) {\n            return;\n        }\n        List<JsPromise> terminal = new ArrayList<>(1);\n        for (JsPromise promise : tracked) {\n            if (!promise.isRejectionHandled() && promise.claimRejectionReport()) {\n                terminal.add(promise);\n            }\n        }\n        if (terminal.isEmpty()) {\n            return;\n        }\n        for (int i = 1; i < terminal.size(); i++) {\n            warn(engine, \"unhandled promise rejection: \" + describe(terminal.get(i).settledValue()));\n        }\n        reportFailure(engine, \"unhandled promise rejection\", terminal.get(0).settledValue());\n    }\n\n    private static void reportFailure(Engine engine, String prefix, Object reason) {\n        if (engine.asyncRejectionWarnOnly()) {\n            warn(engine, prefix + \": \" + describe(reason));\n            return;\n        }\n        throw asEngineException(prefix, reason);\n    }\n\n    private static void warn(Engine engine, String message) {\n        logger.warn(message);\n        java.util.function.Consumer<String> consumer = engine.root().onConsoleLog;\n        if (consumer != null) {\n            consumer.accept(message);\n        }","sourceCodeStart":842,"sourceCodeEnd":878,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/AsyncSupport.java#L842-L878","documentation":"When an async JS chain settles with multiple rejected promises and none is handled, AsyncSupport reports the first rejection (via reportFailure) and logs this warning for each additional unhandled rejection. Karate treats the first unhandled promise rejection as the failure and merely warns about the rest, so developers see 'unhandled promise rejection: <reason>' in logs.","triggerScenarios":"JS code in a Scenario (e.g. karate.callSingle with async, custom async functions, promise chains) where one or more promises reject with no .catch/onRejected handler when the async evaluation completes.","commonSituations":"Forgetting await/catch on a promise inside karate JS; a fetch-like call failing (network, 500) inside an async function; rejecting promises fired after the scenario finished waiting.","solutions":["Add a .catch() or try/await around the failing promise in your JS so rejections are handled","Read the first failure reported — the primary rejection reason is surfaced via reportFailure / engine exception","If rejections should only warn, configure the engine's asyncRejectionWarnOnly mode","Fix the underlying cause in the rejection value (HTTP error, assertion, undefined member)"],"exampleFix":"// before\nkarate.call('async-helper'); // returns promise that rejects\n// after\nreturn karate.call('async-helper').then(r => r).catch(e => { karate.warn('ignored: ' + e); });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// JS: check before using\nfunction isThenable(v) { return v && typeof v.then === 'function'; }\n","tryCatchPattern":"try { await maybeRejecting(); } catch (e) { karate.warn('handled: ' + e); }\n","preventionTips":["Always attach .catch() to promise chains","Await every promise you create","Configure asyncRejectionWarnOnly for non-critical flows","Check logs for secondary rejection warnings after each failure"],"tags":["javascript","async","promise","unhandled-rejection"],"backgroundTag":"unhandled-promise-rejection","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}