{"record":{"id":"c3c16a043ce7edb3","repo":"karatelabs/karate","slug":"karate-boot-js-evaluation-failed-e-getmessage","errorCode":null,"errorMessage":"karate-boot.js evaluation failed: ${e.getMessage()}","messagePattern":"karate-boot\\.js evaluation failed: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"karate-core/src/main/java/io/karatelabs/core/BootLoader.java","lineNumber":89,"sourceCode":"    public static BootBinding evalIfPresent(Suite suite, Path bootstrapWorkingDir, String env) {\n        Resource resource = locate(bootstrapWorkingDir);\n        if (resource == null) {\n            return null;\n        }\n        logger.info(\"{} processed\", BOOT_FILE_NAME);\n        BootBinding boot = new BootBinding(suite, suite == null ? bootstrapWorkingDir : suite.getRoot(), env,\n                suite == null ? e -> {} : suite::registerExtListener);\n        Engine engine = new Engine();\n        // ExternalBridge enables reflective dispatch for plain Java methods on\n        // the bound objects — required for boot.ext(name) / boot.read(path) etc.\n        engine.setExternalBridge(new ExternalBridge() {});\n        engine.putRootBinding(\"boot\", boot);\n        try {\n            engine.eval(resource);\n        } catch (Exception e) {\n            // Boot-time failure is fatal per K43 — re-throw as RuntimeException so\n            // Suite.run()'s caller sees it.\n            throw new RuntimeException(\n                    \"karate-boot.js evaluation failed: \" + e.getMessage(), e);\n        }\n        return boot;\n    }\n\n    /**\n     * Boot-only evaluation: run {@code karate-boot.js} for a project working dir and return the\n     * {@link BootBinding} <b>without running any features</b> (no {@code SUITE_ENTER}/{@code SUITE_EXIT},\n     * no scenarios). The boot side effects — exts constructed + configured via {@code boot.ext(name)} +\n     * {@code .putMember(...)} during the JS eval — are the whole point, so a caller that lives outside a\n     * run (e.g. a persistent serve engine re-deriving a project's per-run {@code cov.*} config) can reach\n     * the booted, configured exts on demand.\n     *\n     * <p>Constructs the minimal {@link Suite} the boot phase needs (this package owns the package-private\n     * Suite construction, so callers don't have to) anchored at {@code workingDir}, and returns the\n     * binding the Suite constructor already evaluated. Returns {@code null} when {@code workingDir} is\n     * null or no {@code karate-boot.js} is present (the no-ext zero-cost path is preserved).</p>\n     *","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/BootLoader.java#L71-L107","documentation":"karate-boot.js is evaluated at suite startup via BootLoader.evalIfPresent, binding a 'boot' object into the JS engine. Any exception thrown while evaluating this bootstrap script is wrapped in a RuntimeException and re-thrown, making the failure fatal to the whole Suite per design decision K43 — the caller of Suite.run() sees it directly.","triggerScenarios":"karate-boot.js exists on the boot classpath/resource path but its evaluation throws — e.g. a JS syntax error in the script, a call to an API that doesn't exist in the embedded engine, or a user-supplied boot script that references missing variables or throws at top level.","commonSituations":"Teams customize karate-boot.js on the classpath to pre-load globals or polyfills; after a Karate version upgrade the old script references removed APIs; a typo or half-edited boot script is committed; the script depends on a resource that isn't packaged into the test jar.","solutions":["Read the wrapped exception's cause (the second argument) and fix the JS error at the reported line in karate-boot.js","Temporarily remove/rename karate-boot.js from the classpath to confirm it is the source of the failure","Update the boot script for the current Karate version's API surface (check docs/MIGRATION_GUIDE.md)","Validate the script with a JS syntax checker or run it in a minimal engine harness before shipping it on the classpath"],"exampleFix":"// before (karate-boot.js)\nvar boot = karate.configure('report', { logLevel: 'INFO' });\n// after\nvar boot = karate.configure('logging', { report: 'info' });","handlingStrategy":"try-catch","validationCode":"// before running the suite, smoke-eval the boot script\ntry { new javax.script.ScriptEngineManager().getEngineByName('js').eval(bootJsSource); } catch (e) { throw new Error('karate-boot.js invalid: ' + e.message); }","typeGuard":"// ensure the boot resource exists on the classpath before Suite.run\nboolean bootPresent = getClass().getResource('/karate-boot.js') != null;","tryCatchPattern":"try { Suite.run(suite); } catch (RuntimeException e) { if (e.getMessage().startsWith('karate-boot.js evaluation failed')) { log.error('Boot script broken, cause:', e.getCause()); } throw e; }","preventionTips":["Keep karate-boot.js minimal and version it with the test codebase","Syntax-check the script in CI before packaging","Re-validate the boot script after every Karate upgrade"],"tags":["javascript","boot","startup","fatal"],"backgroundTag":"module-init-failed","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"}