{"record":{"id":"5632a03cd530bec5","repo":"karatelabs/karate","slug":"hint-names-offending-unquoted-object-literal-keys-containing","errorCode":null,"errorMessage":"${hint: names offending unquoted object-literal keys (containing - or :) and shows the corrected quoted form}","messagePattern":"\\$\\{hint: names offending unquoted object-literal keys \\(containing - or :\\) and shows the corrected quoted form\\}","errorType":"validation","errorClass":"MarkupHintException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/markup/MarkupTemplateContext.java","lineNumber":220,"sourceCode":"\n    public Object evalLocalAsObject(String src) {\n        String temp;\n        if (src.startsWith(\"${\")) {\n            temp = \"`\" + src + \"`\";\n        } else {\n            temp = \"({\" + src + \"})\";\n        }\n        try {\n            return evalLocal(temp);\n        } catch (io.karatelabs.parser.ParserException pe) {\n            // th:attr / ka:with / hx-vals / ka:dispatch values whose keys\n            // contain hyphens or colons (e.g. `data-foo: 'bar'`,\n            // `hx-target: t`, `ka:get: url`) confuse the JS object-literal\n            // parser. Augment the bare parser failure with a hint that names\n            // the offending keys and shows the corrected (quoted) form.\n            String hint = buildAttrKeyHint(src);\n            if (hint != null) {\n                throw new MarkupHintException(hint, pe);\n            }\n            throw pe;\n        }\n    }\n\n    // Detects unquoted attribute-style keys (containing `-` or `:`) at the\n    // start of an object-literal pair. Anchored at start-of-string or after a\n    // comma so it ignores already-quoted keys (`'data-foo':`) and identifiers\n    // inside expression values (`bar - baz`, `obj.x`).\n    private static final java.util.regex.Pattern UNQUOTED_HYPHEN_COLON_KEY =\n            java.util.regex.Pattern.compile(\n                    \"(^|,)\\\\s*([a-zA-Z_$][\\\\w$]*(?:[-:][\\\\w$]+)+)\\\\s*:\");\n\n    private static String buildAttrKeyHint(String src) {\n        java.util.regex.Matcher m = UNQUOTED_HYPHEN_COLON_KEY.matcher(src);\n        java.util.LinkedHashSet<String> badKeys = new java.util.LinkedHashSet<>();\n        while (m.find()) {\n            badKeys.add(m.group(2));","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/markup/MarkupTemplateContext.java#L202-L238","documentation":"When a JS expression inside a markup attribute fails to parse, karate-core augments the bare parser error with a MarkupHintException whose message names the offending unquoted object-literal keys (keys containing '-' or ':') and shows the corrected quoted form. The underlying cause is a JavaScript SyntaxError from the object literal.","triggerScenarios":"Writing attribute expressions like `data-foo: 'bar'` or `ka:get: url` where object keys contain hyphens or colons and are not quoted, e.g. `{ data-foo: 'bar' }`, which the JS object-literal parser rejects.","commonSituations":"HTML-ish attribute habits carried into karate templates (data-* attributes); htmx-style attributes (hx-target); ka: directives with namespaced keys pasted into JS literals.","solutions":["Quote the offending keys: { 'data-foo': 'bar' } instead of { data-foo: 'bar' }","Read the hint message — it lists the exact offending keys and the corrected form","Rewrite expressions that mix directive syntax (ka:get:) directly into object literals","Use camelCase or underscore keys if quoting is undesirable"],"exampleFix":"// before\n<div ka:get=\"{ data-foo: 'bar' }\">\n// after\n<div ka:get=\"{ 'data-foo': 'bar' }\">","handlingStrategy":"validation","validationCode":"// quote any object key containing - or : before writing the attribute\nconst keyNeedsQuotes = k => /[-:]/.test(k);\nconst literal = Object.entries(obj).map(([k,v]) =>\n  `${keyNeedsQuotes(k) ? `'${k}'` : k}: ${JSON.stringify(v)}`).join(', ');","typeGuard":"function safeLiteralKey(k) { return typeof k === 'string' && !/[-:]/.test(k) ? k : `'${k}'`; }","tryCatchPattern":"try { evalAttr(expr); } catch (MarkupHintException e) { log.error(\"fix unquoted keys: \" + e.getMessage()); } ","preventionTips":["Quote all hyphenated/colon-containing object keys in attribute expressions","Follow the hint message — it shows the exact corrected form","Avoid pasting directive syntax (ka:get:) directly into JS object literals"],"tags":["javascript","syntax-error","markup-template","object-literal"],"backgroundTag":"json-parse-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"}