karatelabs/karate · error · MarkupHintException
${hint: names offending unquoted object-literal keys…
Error message
${hint: names offending unquoted object-literal keys (containing - or :) and shows the corrected quoted form} What it means
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.
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
Example fix
// before
<div ka:get="{ data-foo: 'bar' }">
// after
<div ka:get="{ 'data-foo': 'bar' }"> Defensive patterns
Strategy: validation
Validate before calling
// quote any object key containing - or : before writing the attribute
const keyNeedsQuotes = k => /[-:]/.test(k);
const literal = Object.entries(obj).map(([k,v]) =>
`${keyNeedsQuotes(k) ? `'${k}'` : k}: ${JSON.stringify(v)}`).join(', '); Type guard
function safeLiteralKey(k) { return typeof k === 'string' && !/[-:]/.test(k) ? k : `'${k}'`; } Try / catch
try { evalAttr(expr); } catch (MarkupHintException e) { log.error("fix unquoted keys: " + e.getMessage()); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: HTML-ish attribute habits carried into karate templates (data-* attributes); htmx-style attributes (hx-target); ka: directives with namespaced keys pasted into JS literals.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- duplicate __proto__ in an object literal
- context.set() requires a name argument
- ReferenceError: ' ' is not defined — did you mean `_. `?…
- parser state: [ ]
- optional chain is not a valid assignment target
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/5632a03cd530bec5.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/markup/MarkupTemplateContext.java:220
public Object evalLocalAsObject(String src) {
String temp;
if (src.startsWith("${")) {
temp = "`" + src + "`";
} else {
temp = "({" + src + "})";
}
try {
return evalLocal(temp);
} catch (io.karatelabs.parser.ParserException pe) {
// th:attr / ka:with / hx-vals / ka:dispatch values whose keys
// contain hyphens or colons (e.g. `data-foo: 'bar'`,
// `hx-target: t`, `ka:get: url`) confuse the JS object-literal
// parser. Augment the bare parser failure with a hint that names
// the offending keys and shows the corrected (quoted) form.
String hint = buildAttrKeyHint(src);
if (hint != null) {
throw new MarkupHintException(hint, pe);
}
throw pe;
}
}
// Detects unquoted attribute-style keys (containing `-` or `:`) at the
// start of an object-literal pair. Anchored at start-of-string or after a
// comma so it ignores already-quoted keys (`'data-foo':`) and identifiers
// inside expression values (`bar - baz`, `obj.x`).
private static final java.util.regex.Pattern UNQUOTED_HYPHEN_COLON_KEY =
java.util.regex.Pattern.compile(
"(^|,)\\s*([a-zA-Z_$][\\w$]*(?:[-:][\\w$]+)+)\\s*:");
private static String buildAttrKeyHint(String src) {
java.util.regex.Matcher m = UNQUOTED_HYPHEN_COLON_KEY.matcher(src);
java.util.LinkedHashSet<String> badKeys = new java.util.LinkedHashSet<>();
while (m.find()) {
badKeys.add(m.group(2));View on GitHub (pinned to a22eb90246)