JSON troubleshooting
Bad control character in string literal in JSON
Fix unescaped newlines, tabs and other control characters inside JSON strings. See exact JavaScript and Python errors and use serializers to escape values.
What the error means
A JSON string contains an unescaped control character in the range U+0000 through U+001F. Common cases are a literal newline, tab or carriage return inside the quotes. Whitespace between JSON tokens is allowed, but those same characters inside a string must use escapes such as backslash-n or a Unicode escape. Escaping changes the serialized text while preserving the decoded string value.
Exact messages by runtime
Messages depend on the input and runtime version. Node and Python rows were reproduced locally. Other rows cite official documentation or source. Rows marked as fragments or templates preserve the source wording and are not complete exception transcripts. Browsers and libraries may append location details.
| Runtime | Message | Input and evidence |
|---|---|---|
| JavaScript / V8 | SyntaxError: Bad control character in string literal in JSON at position 7 (line 1 column 8) | JSON.parse on {"x":"a<LF>b"}, where <LF> is U+000AReproduced in Node.js 24.21.0 |
| Python | json.decoder.JSONDecodeError: Invalid control character at: line 1 column 8 (char 7) | json.loads on the same literal-LF inputReproduced in Python 3.14.4 |
| Firefox | SyntaxError: JSON.parse: bad control character in string literal | Unescaped control character inside a stringMDN diagnostic wording, location suffix omitted |
| Java / Jackson | has to be escaped using backslash to be included in | Unescaped control character inside a stringExact diagnostic fragment; the character description and context surround it |
| PHP / json_last_error_msg() | Control character error, possibly incorrectly encoded | JSON_ERROR_CTRL_CHAROfficial PHP 8.4 message |
| C# / System.Text.Json | '{0}' is invalid within a JSON string. The string should be correctly escaped. | Source template; {0} describes the offending characterOfficial .NET 10 resource string, path and location suffix omitted |
Causes you can reproduce
A multiline value was inserted into a template
A template literal contains a real line feed. Inserting it between JSON quotes leaves that line feed unescaped.
const text = `{"x":"a\nb"}`;
JSON.parse(text);The source language consumed the backslash
In an ordinary Python source string, backslash-n becomes a newline before json.loads sees the text. A raw string preserves the JSON escape.
import json
json.loads('{"x":"a\nb"}') # Python turns \n into a literal newlineA raw tab or carriage return entered a quoted value
Pasting a tab or interpolating text with carriage returns into manually generated JSON can introduce the same error. Serialize the original value instead.
const text = '{"x":"a' + String.fromCharCode(9) + 'b"}';
JSON.parse(text);How to fix it
- Inspect the original string near the reported position. Make invisible characters visible with JSON.stringify(text) in JavaScript or repr(text) in Python.
- Identify whether the character is inside a quoted value. Newlines outside strings can be valid formatting whitespace.
- Serialize the original data structure so the serializer escapes control characters. When editing JSON text directly, replace a literal newline inside a string with the two characters backslash and n.
- Parse the result and check that the decoded value still contains the intended newline or tab.
Let JavaScript escape the original string
The value contains a real newline. JSON.stringify writes its escaped representation, and JSON.parse restores that newline in the decoded value.
const value = { x: 'a\nb' };
const text = JSON.stringify(value);
console.log(text); // {"x":"a\nb"}
const data = JSON.parse(text);
console.log(data.x === value.x); // trueUse json.dumps or a raw JSON literal in Python
The raw source string preserves backslash-n for the JSON parser. For generated data, json.dumps is the safer choice.
import json
value = {"x": "a\nb"}
text = json.dumps(value)
assert json.loads(text) == value
# A hand-written JSON literal with a JSON escape:
data = json.loads(r'{"x":"a\nb"}')Find the exact position with Tool Kumar
- Copy the exact input text, including its original whitespace. For HTTP failures, copy the raw response body.
- Open the Tool Kumar JSON validator and paste the text. The document stays in your browser.
- Read the line and column in the error or fixable-issue banner. For an invalid document, select Go to error to move the caret to that location.
- Inspect the preceding token as well as the marked character. A parser marks where it discovered the problem; the missing quote, separator or value can start earlier.
Python character offsets are zero-based, while its displayed lines and columns are one-based. V8 string positions count UTF-16 code units; Go offsets count bytes read. Unicode text can make these offsets differ. Use the original text and its line/column context rather than copying an offset between runtimes.
Tool Kumar can classify some input as fixable loose JSON. Review a proposed change before using the repair action, then validate the result against your API contract. For empty input, inspect the producer or response because there is no character to select.
Frequently asked questions
Can JSON strings contain newlines?
The decoded string can contain a newline. The JSON text must represent it with an escape such as backslash-n. A literal line feed between the string quotes is invalid.
Are newlines between object members allowed?
Yes. Line feed, carriage return, tab and space can separate JSON tokens. The restriction applies to unescaped control characters inside strings.
Should I use Python strict=False?
strict=False allows raw control characters inside strings, but the input remains outside standard JSON. Fix the producer when the document must work across strict parsers.
Why did adding a backslash not fix my source string?
Your source language may consume the escape before the JSON parser receives it. Inspect the resulting text. Use a serializer, or preserve the backslash with the appropriate source-string syntax.
Related errors and tools
- Expecting property name enclosed in double quotes
- JSONDecodeError: Extra data and multiple JSON values
- All JSON error guides
- JSON syntax reference
Standards and diagnostic sources
RFC 8259 and ECMA-404 define JSON syntax. Diagnostic wording belongs to the parser. The table links each cited message to its source.