Unterminated string starting at: line N column N (char N)

ErrorPython

json.decoder.JSONDecodeError: Unterminated string starting at: line 3 column 11 (char 23)

Where JSON.parse stops

{
  "id": 7,
  "name": "Ada Lov

What it means

Python opened a string and reached the end of the document before the string closed. So the body was most likely cut off. The position is where the string started, not where the text ends.

Last verified on Python 3.9, 3.11, 3.12, 3.13 and 3.14.

The validator opens with the error marked. Examples travel in the URL fragment, which browsers never send to a server.

Express Lint lays broken JSON out by bracket depth and marks the line where it stops. It changes only spaces and line breaks outside strings. Strings in either quote stay as written. If the quotes do not pair up, it leaves your text as it is. Ctrl+Z undoes it. See how it works.

Usually
The body was cut offExpecting ',' delimiter: a missing quote on one lineInvalid control character: a missing quote across lines
Fix
Get the whole document.

The fix

Get the whole document. In the example the rest of the string and the closing } are missing, and the fixed version has both. If the text really was cut off, no edit brings the missing part back, so find out why it stopped.

broken.jsonFails to parse
{
  "id": 7,
  "name": "Ada Lov
JSON.parse reaches the end of the text before the document is complete.

Lines 3 and 4 change.

fixed.jsonParses
{
  "id": 7,
  "name": "Ada Lovelace"
}
JSON.parse reads it.

How the message appears

CPython's json module reports line, column and character offset. The offset in the first line is where the string started, not where the document ends. The next two are what a missing closing quote gives when the string does not run to the end. Python 3.9 to 3.14 print the same for all three.

Console
  • json.decoder.JSONDecodeError: Unterminated string starting at: line 3 column 11 (char 23)
  • json.decoder.JSONDecodeError: Expecting ',' delimiter: line 1 column 17 (char 16)
  • json.decoder.JSONDecodeError: Invalid control character at: line 2 column 25 (char 26)

What causes it

  1. The body was cut off

    A response that stopped halfway, a file that was only partly written, or a buffer that was too small. The document ends in the middle of a string, as the example does, so Python runs out of text before the closing quote. Compare the length of what you got with what was sent, and find out why it stopped.

  2. Expecting ',' delimiter: a missing quote on one line

    If a closing quote is missing but more text follows on the same line, the string ends at the next quote it finds. In {"name": "Ada, "id": 7} the string runs from "Ada, to the quote before id, so Python reports a missing comma at the i. See Expecting ',' delimiter.

  3. Invalid control character: a missing quote across lines

    In a document with line breaks, a string with no closing quote runs on to the end of its line. The line break is not allowed inside a string, so Python reports Invalid control character at and the position is that line break. See Invalid control character.

Worth knowing

NoteIn the example, char 23 is the opening quote of "Ada Lov. Python reports where the string began so you can find the string that never closed.

Your JSON and text are processed entirely in your browser and are never sent anywhere. To understand how the site is used we record each page view (the page, the referrer and an approximate location from your IP address) and keep it for 90 days. Nothing is stored on your device unless you choose it. Accept to also store a device identifier here and record your browser and device characteristics, which is what lets a return visit be told from a new one. Decline and nothing is sent at all. We respect Do Not Track. See our privacy policy.