karatelabs/karate · error
Invalid control character in JSON string
Error message
Invalid control character in JSON string
What it means
Thrown by JsonParser.parseString when a raw control character (code point below 0x20, e.g. tab, newline, NUL) appears unescaped inside a JSON string. RFC 8259 forbids literal control characters in strings — they must be written as escapes like '\n' or '\t'.
Solutions
- Replace literal control characters in the string with their escapes: newline → '\n', tab → '\t', carriage return → '\r'.
- Strip or sanitize control characters before parsing if they are noise.
- Serialize the source data with a JSON encoder so control chars are escaped automatically.
- Check the data source for binary corruption (NUL bytes) and re-fetch clean data.
Example fix
// before
'{"text": "line1
line2"}' // literal newline
// after
'{"text": "line1\nline2"}' Defensive patterns
Strategy: validation
Validate before calling
// Sanitize raw control characters before parsing
static String escapeControlChars(String s) {
StringBuilder sb = new StringBuilder(s.length());
for (char c : s.toCharArray()) {
if (c < 0x20) sb.append(String.format("\\u%04x", (int) c));
else sb.append(c);
}
return sb.toString();
} Try / catch
try {
return Json.parse(raw);
} catch (JsonSyntaxException e) {
if (e.getMessage().contains("control character")) {
return Json.parse(escapeControlChars(raw));
}
throw e;
} Prevention
- Never paste multi-line text directly into JSON string literals — escape newlines as \n.
- Serialize text data with a JSON encoder, which escapes control chars automatically.
- Open files in text (not binary) mode and strip NUL bytes from external data.
- Normalize line endings when copying content between systems.
When it happens
Trigger: Parsing JSON where a string value contains a literal newline/tab (e.g. multi-line text pasted between quotes), a NUL byte from binary corruption, or un-escaped terminal output captured into a string.
Common situations: Copy-pasting multi-line text into a JSON string literal, log files with raw newlines inside values, data fetched from sources that don't escape control chars, corruption from binary reads.
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
- Expected ':' after object key
- Expected string key in object
- Invalid escape '\ ' in JSON string
- Invalid literal — expected 'false'
- Invalid literal — expected 'null'
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/f53d762f0b95d193.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsonParser.java:229
case 'n':
sb.append('\n');
break;
case 'r':
sb.append('\r');
break;
case 't':
sb.append('\t');
break;
case 'u':
sb.append(parseHex4());
break;
default:
throw syntaxError("Invalid escape '\\" + esc + "' in JSON string");
}
continue;
}
if (c < 0x20) {
throw syntaxError("Invalid control character in JSON string");
}
sb.append(c);
pos++;
}
throw syntaxError("Unterminated JSON string");
}
private char parseHex4() {
if (pos + 4 > len) {
throw syntaxError("Invalid \\u escape in JSON string");
}
int v = 0;
for (int i = 0; i < 4; i++) {
char h = s.charAt(pos + i);
int d;
if (h >= '0' && h <= '9') d = h - '0';
else if (h >= 'a' && h <= 'f') d = 10 + (h - 'a');
else if (h >= 'A' && h <= 'F') d = 10 + (h - 'A');View on GitHub (pinned to a22eb90246)