{"record":{"id":"a6ca51a058786f5a","repo":"karatelabs/karate","slug":"referenceerror-missing-is-not-defined-did-you-mean-missing","errorCode":null,"errorMessage":"ReferenceError: '${missing}' is not defined — did you mean `_.${missing}`? ka:scope blocks namespace template state via the `_` map; ...","messagePattern":"ReferenceError: '(.+?)' is not defined — did you mean `_\\.(.+?)`\\? ka:scope blocks namespace template state via the `_` map; \\.\\.\\.","errorType":"validation","errorClass":"MarkupHintException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/markup/MarkupTemplateContext.java","lineNumber":282,"sourceCode":"        Map<String, Object> localVars = new HashMap<>();\n        for (String name : getVariableNames()) {\n            localVars.put(name, getVariable(name));\n        }\n        // Bind `_` as the dual-lookup ObjectLike (not the raw vars Map)\n        // so template-attribute reads of `_.<name>` fall through to the\n        // wrapped Thymeleaf scope when the underscore map is empty.\n        localVars.put(\"_\", underscoreView);\n        // Strict ReferenceError on missing names — augment with an actionable\n        // hint pointing at either the `_.<name>` discipline or the\n        // th:with-at-call-site / context.get(...) optional-param pattern.\n        try {\n            return engine.evalWith(src, localVars);\n        } catch (io.karatelabs.js.EngineException e) {\n            String missing = extractMissingName(e);\n            if (missing == null) {\n                throw e;\n            }\n            throw new MarkupHintException(buildMissingNameHint(missing, e), e);\n        }\n    }\n\n    private String buildMissingNameHint(String missing, Throwable cause) {\n        String base = \"ReferenceError: '\" + missing + \"' is not defined\";\n        if (vars.containsKey(missing)) {\n            return base + \" — did you mean `_.\" + missing + \"`? \"\n                    + \"ka:scope blocks namespace template state via the `_` map; \"\n                    + \"bare names must come from a th:with or a parent template binding.\";\n        }\n        return base + \" — if `\" + missing + \"` is a fragment parameter, \"\n                + \"declare it via th:with at the call site \"\n                + \"(e.g. <div th:insert=\\\"~{file::frag}\\\" th:with=\\\"\" + missing + \": value\\\">). \"\n                + \"If it's optional, read it inside the fragment via \"\n                + \"context.get('\" + missing + \"') or context.get('\" + missing + \"', defaultValue) — \"\n                + \"returns null (or the default) when the name is unbound.\";\n    }\n","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/markup/MarkupTemplateContext.java#L264-L300","documentation":"When JS evaluation in a markup template fails with a ReferenceError for an unknown name, karate-core checks whether the name exists in the template vars and produces a MarkupHintException suggesting `_.<name>`. ka:scope blocks namespace template state via the `_` map, so a variable set in scope is accessed as `_.name`, not as a bare global.","triggerScenarios":"Referencing a bare identifier inside a template (or inside a ka:scope block) that was stored via context.set() / `_.x = value`, e.g. writing `count` instead of `_.count`; typo'd variable names; variables that only exist in localVars but were shadowed.","commonSituations":"Authors forgetting the `_` namespace prefix after moving code into a ka:scope block; migration from older templates where variables were plain globals; typos in template variable names.","solutions":["Prefix the variable with `_.` as the hint suggests: `_.count` instead of `count`","Verify the exact variable name spelling against what was set via context.set() or `_.x =`","If the value should be a plain template variable, define it in the template model instead of the scope map","Check whether the code was moved into/out of a ka:scope block, which changes the namespace"],"exampleFix":"// before\n<span>${count}</span>\n// after\n<span>${_.count}</span>","handlingStrategy":"type-guard","validationCode":"// check the name exists in the underscore scope before use\nif (!_.hasOwnProperty(name)) throw new Error(name + \" not in _ scope; set it via context.set\");","typeGuard":"function scopeRef(name) { return typeof _[name] !== 'undefined' ? _[name] : undefined; }","tryCatchPattern":"try { evalTemplate(expr); } catch (MarkupHintException e) { if (e.getMessage().contains(\"is not defined\")) { log.error(\"scope hint: \" + e.getMessage()); } else throw e; }","preventionTips":["Prefix scope-stored variables with `_` inside ka:scope blocks","Verify spelling against what context.set() stored","Keep scope variables documented per template to avoid namespace confusion"],"tags":["javascript","reference-error","markup-template","scoping"],"backgroundTag":"reference-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"}