Unterminated string in JSON: How to Fix It in Python
Python raises JSONDecodeError: Unterminated string starting at when a string has no closing quote. Learn the common causes and how to fix them with…
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →Python raises this when json.loads() finds an opening double quote and reaches the end of the text without a matching closing quote. Add the missing quote, or fix whatever cut the text short, and the string parses.
What “Unterminated string in JSON” means
The parser found a string that never ends. In JSON, a string starts with a double quote and must end with another double quote (RFC 8259). Python's json module reads from the opening quote to the end of the input. If it finds no closing quote, it raises JSONDecodeError with the message 'Unterminated string starting at', plus the line, column and character offset of the opening quote. That position points at where the string began, not where the text broke off.
Causes and the fix for each
The closing quote is missing.
A value was typed or generated with an opening quote and no closing one, so the parser runs to the end of the text.
Before (fails):{"name": "Ada}
After (valid):
{"name": "Ada"}
The text was cut off before it finished.
A token limit, a network drop or a partial file read can stop the text in the middle of a string. LLM output that hits max_tokens often ends this way.
Before (fails):{"text": "Hello wor
After (valid):
{"text": "Hello world"}
A trailing backslash escapes the closing quote.
In JSON a backslash starts an escape. A backslash right before the last quote turns that quote into a literal character, so the string stays open. This often happens with Windows paths.
Before (fails):{"path": "C:\temp\"}
After (valid):
{"path": "C:\\temp\\"}
A curly quote closes the string instead of a straight quote.
Text copied from a word processor or a chat window can contain the characters ” or “. JSON only accepts the plain double quote character, so the parser does not see an end.
Before (fails):{"name": "Ada”}
After (valid):
{"name": "Ada"}
How to fix it in Python
- Read the position in the error. 'line 1 column 10 (char 9)' is where the unterminated string starts. Print text[e.pos:e.pos + 60] to see the string that never closed.
- Look at the end of the text. If it stops in the middle of a word, the data was truncated. Fix the source: raise the token limit, read the full response, or check that the file was written completely.
- If the text is complete, look for a missing quote, a trailing backslash or a curly quote near the reported position. Replace or escape it so the string ends with a plain double quote.
- Paste the text into the Repair tool to close open strings and brackets automatically, then check the result against what you expected. Use the Validator to confirm the output is valid JSON.
- If you build the JSON yourself, stop concatenating strings. Pass a dict to json.dumps() so quotes and backslashes are escaped for you.
import json
def parse_json(text):
try:
return json.loads(text)
except json.JSONDecodeError as e:
if "Unterminated string" not in e.msg:
raise
# Log the spot where the open string begins.
print(f"Open string at char {e.pos}: {text[e.pos:e.pos + 60]!r}")
# Last resort for truncated data: close the string and the object.
# This may drop or cut the last value, so check the result.
try:
return json.loads(text + '"}')
except json.JSONDecodeError:
raise e
Variants of the message
| Message | Cause | Fix |
|---|---|---|
| Unterminated string starting at: line 1 column 10 (char 9) | A string opens at that position and has no closing quote. | Add the closing quote or restore the truncated text. |
| Invalid control character at: line 2 column 12 (char 20) | A raw newline or tab sits inside a string. | Escape it as \n or \t. |
| Expecting ',' delimiter: line 1 column 20 (char 19) | An unescaped quote inside a string ended it early. | Escape the inner quote as \". |
| Invalid \escape: line 1 column 12 (char 11) | A backslash is followed by a character JSON does not allow. | Double the backslash. |
| Expecting value: line 1 column 1 (char 0) | The text is empty or does not start with JSON. | Check that the response body is not empty or HTML. |
Related errors
- Invalid control character in JSON: How to Fix It in Python
- JSONDecodeError: Expecting ',' delimiter: How to Fix It in Python
- Fix Python JSON Errors: json.loads() Decode Errors and How to Repair Them
- Invalid JSON Meaning: What It Is and How to Fix It
- How to Fix Claude API 400 Errors in JSON Tool Calls (2026)
Key takeaways
- The error means a string was opened and never closed.
- The reported position is the opening quote of that string.
- Truncated text, a trailing backslash and curly quotes are the usual causes.
- Build JSON with json.dumps() instead of string concatenation.
- Use the Repair tool to close broken strings, then check the result.
FAQ
Why does the error point to the start of the string and not the end?
Python reports where the string began. The parser has no way to know where the string should have ended, so it reports the opening quote.
Why do I get this error with LLM output?
The model often hits the max_tokens limit in the middle of a string. The JSON then stops without a closing quote. Check the stop reason, raise the limit, or repair the output before parsing.
Does a newline inside a string cause this error?
Not in Python's default mode. A raw newline in a string raises 'Invalid control character'. RFC 8259 requires control characters to be escaped.
Can I fix it by switching to single quotes?
No. JSON strings must use double quotes. Single quotes cause a different error, such as 'Expecting property name enclosed in double quotes'.
Is appending a quote and a brace a safe fix?
It only works for simple truncation and can hide data loss. The last value may be cut short. Use it as a fallback and check the result.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles