{"record":{"id":"54e33dbd520aeaae","repo":"karatelabs/karate","slug":"js-exception-for","errorCode":null,"errorMessage":"JS exception for: {} -> {}","messagePattern":"JS exception for: (.+?) -> (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":2020,"sourceCode":"        return frameContexts.get(currentFrame.id);\n    }\n\n    private Object extractJsValue(CdpResponse response, String expression) {\n        if (response.isError()) {\n            String message = response.getErrorMessage();\n            if (message != null && message.contains(\"Object reference chain is too long\")) {\n                logger.debug(\"script result not serializable, returning null: {}\", truncate(expression, 100));\n                return null;\n            }\n            logger.warn(\"JS error for expression: {}\", truncate(expression, 100));\n            throw new RuntimeException(\"JS error: \" + response.getError());\n        }\n        Object exceptionDetails = response.getResult(\"exceptionDetails\");\n        if (exceptionDetails != null) {\n            // Try to get detailed error message from exception object\n            String description = response.getResultAsString(\"exceptionDetails.exception.description\");\n            if (description != null && !description.isEmpty()) {\n                logger.warn(\"JS exception for: {} -> {}\", truncate(expression, 100), truncate(description, 200));\n                throw new RuntimeException(\"JS exception: \" + description);\n            }\n            // Fall back to text (usually just \"Uncaught\")\n            String text = response.getResultAsString(\"exceptionDetails.text\");\n            logger.warn(\"JS exception for: {} -> {}\", truncate(expression, 100), text);\n            throw new RuntimeException(\"JS exception: \" + text);\n        }\n        Object value = response.getResult(\"result.value\");\n        logger.trace(\"script result: {}\", value);\n        return value;\n    }\n\n    // ========== Screenshot ==========\n\n    /**\n     * Take screenshot and return PNG bytes.\n     */\n    public byte[] screenshot() {","sourceCodeStart":2002,"sourceCodeEnd":2038,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L2002-L2038","documentation":"When Runtime.evaluate returns exceptionDetails, CdpDriver throws RuntimeException(\"JS exception: <description>\") using the exception object's description. This means the JavaScript expression executed via driver.script()/eval threw an uncaught error in the browser. The library surfaces the browser-side message so the caller can see the actual JS failure rather than a generic CDP error.","triggerScenarios":"Calling script(html, expression) or CdpDriver.script() with a JS expression that throws at evaluation time — e.g. referencing an undefined variable, calling a method on null/undefined, or JSON.parse of invalid data. The description branch is taken when exceptionDetails.exception.description is present (typical for Error/TypeError objects).","commonSituations":"Typos in injected JS, page scripts not yet defining a global the expression relies on, evaluating in the wrong frame/context where the expected object doesn't exist, or Chrome's stricter JS engine rejecting code that worked elsewhere.","solutions":["Read the description after 'JS exception: ' — it contains the browser's actual error (line number, message); fix the JS accordingly.","Guard the expression: wrap risky JS in try/catch inside the expression, or check typeof before dereferencing (e.g. \"window.foo ? foo.bar : null\").","Ensure the correct frame is active (switchFrame) before evaluating — the symbol may exist only in another frame.","Wait for the page to be ready (waitForUrl / implicit waits) so page globals exist before eval."],"exampleFix":"// before\nString title = driver.script(\"document\", \"_.title || missingGlobal.name\");\n// after\nString title = driver.script(\"document\", \"typeof missingGlobal !== 'undefined' ? missingGlobal.name : _.title\");","handlingStrategy":"try-catch","validationCode":"// before eval, ensure the symbol exists\nBoolean ok = (Boolean) driver.script(\"window\", \"typeof paymentConfig !== 'undefined'\");\nif (!Boolean.TRUE.equals(ok)) { driver.waitFor(\"#config-loaded\"); }","typeGuard":null,"tryCatchPattern":"try {\n    Object result = driver.script(\"document\", expr);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"JS exception: \")) {\n        // browser-side JS threw: fix expr or wait for page readiness\n    }\n    throw e;\n}","preventionTips":["Test expressions in the browser DevTools console before embedding them","Use typeof checks inside expressions instead of bare dereferences","Wait for page/frame readiness before evaluating","Throw Error objects (not strings) in page code so descriptions are detailed"],"tags":["javascript","cdp","runtime-evaluate","browser-driver"],"backgroundTag":"js-runtime-evaluation-error","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"}