{"record":{"id":"186c46088cfbdffe","repo":"karatelabs/karate","slug":"ext-name-reportassets-js-is-required","errorCode":null,"errorMessage":"ext '<name>': ReportAssets.js(...) is required","messagePattern":"ext '<name>': ReportAssets\\.js\\(\\.\\.\\.\\) is required","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"karate-core/src/main/java/io/karatelabs/core/ReportAssets.java","lineNumber":169,"sourceCode":"\n    /** The ext-supplied CTA label, or null if this ext registered none. */\n    public String ctaLabel() {\n        return ctaLabel;\n    }\n\n    /** The ext-supplied CTA href, or null if this ext registered none. */\n    public String ctaHref() {\n        return ctaHref;\n    }\n\n    /**\n     * Validate the spec against {@code classLoader} and bind it for later copying.\n     * Throws (failing the Suite at boot) when {@code js} is unset or a referenced\n     * resource is missing.\n     */\n    void validateAndBind(ClassLoader classLoader) {\n        if (js == null || js.isBlank()) {\n            throw new RuntimeException(\"ext '\" + name + \"': ReportAssets.js(...) is required\");\n        }\n        requireResource(classLoader, js, \"js\");\n        if (css != null) {\n            requireResource(classLoader, css, \"css\");\n        }\n        for (String a : assets) {\n            requireResource(classLoader, a, \"asset\");\n        }\n        for (Page p : pages) {\n            if (p.href() != null) {\n                requireResource(classLoader, p.href(), \"page\");\n            }\n        }\n        this.classLoader = classLoader;\n    }\n\n    /**\n     * Copy the declared assets (JS, optional CSS, page HTML) into {@code extDir}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/ReportAssets.java#L151-L187","documentation":"ReportAssets.validateAndBind checks each registered report extension spec at Suite boot: a spec without a JS entry is invalid because the extension has no client-side code to run. The failure is deliberately thrown at boot so misconfigured extensions fail the whole Suite early.","triggerScenarios":"Registering a ReportAssets spec via registerReportAssets without calling .js(path), or calling js(\"\") / js(\"   \").","commonSituations":"Building the spec conditionally and skipping the js() call; renaming an extension and forgetting its JS registration; copying a spec template with the js() line removed.","solutions":["Call .js(\"classpath:my-ext.js\") (or relative path) on the ReportAssets spec before registration","Verify the js path points at an existing classpath resource — the next validation step requires it","Check that every registered spec in registerReportAssets completes its builder chain with js(...)"],"exampleFix":"// before\nReportAssets.named(\"my-ext\").css(\"style.css\")\n// after\nReportAssets.named(\"my-ext\").js(\"ext/my-ext.js\").css(\"ext/style.css\")","handlingStrategy":"validation","validationCode":"void check(ReportAssets a) { if (!a.toString().contains(\"js\")) throw new IllegalStateException(\"spec missing js()\"); }\n// simpler: enforce in your own builder wrapper that js(...) is always called before registerReportAssets","typeGuard":null,"tryCatchPattern":"try { suite.registerReportAssets(specs); } catch (RuntimeException e) { if (e.getMessage().contains(\"ReportAssets.js(...) is required\")) { log.error(\"Extension spec missing js(): {}\", e.getMessage()); } throw e; }","preventionTips":["Build ReportAssets specs through a shared helper that always appends .js(...)","Add a unit test asserting every registered spec has a js path","Fail fast in your own config loader when the js path property is absent"],"tags":["reporting","validation","configuration","boot-failure"],"backgroundTag":"missing-required-config-field","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"}