{"record":{"id":"cdfc72e2fa910c2d","repo":"karatelabs/karate","slug":"doc-requires-read-key-with-template-path","errorCode":null,"errorMessage":"doc() requires 'read' key with template path","messagePattern":"doc\\(\\) requires 'read' key with template path","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/KarateJs.java","lineNumber":154,"sourceCode":"        if (_markup == null) {\n            if (resourceResolver != null) {\n                _markup = Markup.init(engine, resourceResolver);\n            } else {\n                _markup = Markup.init(engine, root.getPrefixedPath());\n            }\n        }\n        return _markup;\n    }\n\n    /**\n     * Renders an HTML template and returns the result.\n     * Also sends to onDoc consumer if set.\n     * Called by the 'doc' keyword in StepExecutor.\n     */\n    public String doc(Map<String, Object> options) {\n        String read = (String) options.get(\"read\");\n        if (read == null) {\n            throw new RuntimeException(\"doc() requires 'read' key with template path\");\n        }\n        String html = markup().processPath(read, null);\n        if (onDoc != null) {\n            onDoc.accept(html);\n        }\n        return html;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private JavaInvokable doc() {\n        return args -> {\n            if (onDoc == null) {\n                logger.warn(\"doc() called, but no destination set\");\n                return null;\n            }\n            if (args.length == 0) {\n                throw new RuntimeException(\"doc() needs at least one argument\");\n            }","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/KarateJs.java#L136-L172","documentation":"The doc() keyword renders an HTML template and sends it to a registered onDoc consumer (e.g. a report or driver). When called with an options Map, that Map must contain a 'read' key holding the template path; a missing/null 'read' throws this error.","triggerScenarios":"Calling doc with a map lacking 'read': doc({ title: 'x' }), or doc({ read: null }) — typically from a JS call site building the options object dynamically.","commonSituations":"Refactoring a doc() call from positional-args form to map form (or vice versa) and losing the 'read' key; a variable interpolating to null; typo like 'path:' instead of 'read:'.","solutions":["Add the 'read' key with the template path: doc({ read: 'classpath:doc/template.html' })","Verify the variable holding the path is not null at call time","Check the doc() signature you're using — map form requires 'read', positional form takes the path as the first argument"],"exampleFix":"// before\n* doc({ title: 'My Doc' })\n// after\n* doc({ read: 'classpath:docs/template.html', title: 'My Doc' })","handlingStrategy":"validation","validationCode":"// before calling doc with a map\nif (!opts || !opts.read) { throw 'doc options require read: <template path>'; }","typeGuard":"function hasRead(opts) { return opts != null && typeof opts.read === 'string' && opts.read.length > 0; }","tryCatchPattern":"try { karate.doc(opts); } catch (RuntimeException e) { if (e.getMessage().contains(\"requires 'read' key\")) { log.error('doc options map must include read'); } throw e; }","preventionTips":["Always build doc options with a literal read key","Avoid dynamic option maps unless read is guaranteed","Centralize doc() calls in a helper that validates options"],"tags":["doc","missing-argument","templates","javascript"],"backgroundTag":"missing-required-argument","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"}