← All articles

Unterminated String in JSON: Causes and Fixes

Fix unterminated JSON strings by finding the open quote, escaped closing quote, raw newline, or truncated response that left the value incomplete.

SyntaxError: Unterminated string in JSON means the parser entered a JSON string after an opening double quote, but never found the matching closing double quote in the place the grammar requires it.

The bug is narrower than "my JSON is invalid." It is specifically about a string value or object key that did not close cleanly. The usual causes are a missing quote, a closing quote accidentally escaped by a backslash, a raw newline inside the string, or data that was cut off before the string ended.

According to RFC 8259 section 7, JSON strings begin and end with quotation marks, and quotes, backslashes, and control characters must be escaped. JSON.parse() enforces that grammar.

Quick Diagnosis

Start by looking at the string around the reported position, line, or column. Then match the shape of the broken text.

Broken input shape Likely cause Correct fix
{ "name": "Ada } Missing closing quote Add the closing quote before the object continues
{ "path": "C:\\logs\" } Backslash escaped the intended closing quote Escape the final backslash as \\ before the quote
{ "bio": "line one followed by a real line break Raw newline inside the string Use \n inside the JSON string
{"message":"upload started at the end of the body Response or file was truncated Re-fetch, fix buffering, or repair the producer
{ "note": "He said "ok"" } Inner quote closed the string early Escape inner quotes or use JSON.stringify()

That last case may not always show the exact "unterminated string" wording. Many engines report it as an unexpected token after the premature quote. It belongs in the same debugging neighborhood, but the fix is different from blindly adding a quote at the end.

What the Error Looks Like

Parser wording varies by engine:

// V8 in Chrome, Edge, and Node.js
SyntaxError: Unterminated string in JSON at position 27

// Firefox
SyntaxError: JSON.parse: unterminated string at line 2 column 10 of the JSON data

// Safari
SyntaxError: JSON Parse error: Unterminated string

// Python may use a related wording
json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 12 (char 11)

If the engine gives a numeric position, treat it as a starting clue rather than a perfect answer. The reported index may point at the opening quote, the end of input, or the spot where the parser realized it could not continue.

Locate the Open String

In browser code, Node scripts, or test helpers, use a small diagnostic wrapper that shows a safe window around the error. Do not dump full production payloads into logs when they might contain tokens, cookies, emails, or customer records.

function describeJsonParseFailure(text, error) {
  const positionMatch = /position (\d+)/.exec(error.message);

  if (!positionMatch) {
    return {
      message: error.message,
      preview: JSON.stringify(text.slice(0, 160)),
    };
  }

  const position = Number(positionMatch[1]);
  const start = Math.max(0, position - 60);
  const end = Math.min(text.length, position + 60);

  return {
    message: error.message,
    position,
    before: JSON.stringify(text.slice(start, position)),
    at: JSON.stringify(text[position] ?? ""),
    after: JSON.stringify(text.slice(position + 1, end)),
  };
}

try {
  JSON.parse(rawJson);
} catch (error) {
  console.log(describeJsonParseFailure(rawJson, error));
}

For multi-line text, mapping a character index to line and column is more useful:

function indexToLineColumn(text, index) {
  const before = text.slice(0, index);
  const lines = before.split(/\r?\n/);

  return {
    line: lines.length,
    column: lines[lines.length - 1].length + 1,
  };
}

Once you have the line, inspect from the opening quote forward. You are looking for one of four things: the quote is missing, the quote is escaped, the line broke before the quote, or the input ended too soon.

Cause 1: The Closing Quote Is Missing

The simplest broken input is a string that starts but never closes:

{
  "status": "uploading,
  "progress": 42
}

The parser sees "uploading and keeps scanning for the closing quote. It reaches the comma and the next key while still inside the string, so the document is no longer valid JSON.

Fix the string, then validate the whole object:

{
  "status": "uploading",
  "progress": 42
}

When this happens in hand-edited config, the quote is often missing near a long description, URL, SQL fragment, or shell command. When it happens in generated JSON, the real fix is not to add quotes manually. Fix the serializer.

Cause 2: The Closing Quote Was Escaped by Accident

This one is easy to miss because the closing quote is visible on the screen:

{
  "path": "C:\\exports\"
}

The final \" does not close the string. In JSON, it means "put a quote character inside the string." The parser then reaches the newline or closing brace while still waiting for the real string terminator.

If the value should end with a backslash, escape the backslash itself:

{
  "path": "C:\\exports\\"
}

This shows up often in Windows paths, generated file paths, regular expressions, and copied command-line snippets. If you are building the JSON in JavaScript, do not manually assemble the text:

const payload = {
  path: "C:\\exports\\",
};

const json = JSON.stringify(payload);

JSON.stringify() will escape the backslashes and quotes correctly for JSON output.

Cause 3: A Raw Newline Is Inside the String

JSON strings cannot contain a literal line break. This is broken:

{
  "bio": "first line
second line"
}

Use the escape sequence \n instead:

{
  "bio": "first line\nsecond line"
}

Some parsers call the raw line break an "unterminated string." Others call it a bad control character, because a line feed is a control character inside a JSON string. Either way, the repair is the same: the newline must be escaped inside the string, or the producer must serialize the value instead of pasting it into JSON text.

The JavaScript version should look like this:

const bio = `first line
second line`;

const json = JSON.stringify({ bio });

Do not try to create the JSON by concatenating:

const broken = '{ "bio": "' + bio + '" }';

That line creates invalid JSON as soon as bio contains a newline, a quote, or a backslash.

Cause 4: The Response Was Truncated Mid-String

If the input ends in the middle of a value, the parser has no quote to find:

{"user":{"id":42,"name":"Ada Lovel

This is not a "repair the text and move on" problem if the data came from an API. The server, proxy, worker, storage layer, or stream reader did not deliver the whole body.

Check for these clues:

Clue What to inspect
Body length is shorter than expected Content-Length, compressed response handling, proxy limits
Error appears only on large records gateway limits, Lambda or worker response limits, database field truncation
Error appears in streaming code chunk boundaries and whether you parse before the stream ends
Error appears in logs only log truncation, clipboard truncation, terminal line limits
Error appears after deployment new middleware, minifier, CDN, or error handler changing the body

A fetch wrapper can make this easier to diagnose:

async function readJsonWithLengthCheck(response) {
  const expectedLength = response.headers.get("content-length");
  const text = await response.text();

  if (expectedLength && Number(expectedLength) !== new TextEncoder().encode(text).length) {
    throw new Error(
      `JSON body length mismatch: expected ${expectedLength}, received ${text.length} characters`,
    );
  }

  return JSON.parse(text);
}

Be careful with compressed responses and multibyte characters when comparing lengths. Content-Length counts bytes on the wire for the encoded body, while JavaScript string length counts UTF-16 code units. The check above is a debugging aid, not a universal transport validator.

Cause 5: An Inner Quote Closed the String Too Early

This input is invalid:

{
  "note": "He said "ship it" during review"
}

The parser may not say "unterminated string." It may say Unexpected token s, Expected comma, or something similar, because "He said " was technically closed before ship. Still, developers often arrive here while searching for unterminated string fixes.

The correct JSON is:

{
  "note": "He said \"ship it\" during review"
}

The better fix is to let the serializer handle it:

const note = 'He said "ship it" during review';
const json = JSON.stringify({ note });

This matters for support messages, LLM output, product descriptions, CSV fields, SQL fragments, and any user-entered text. User input is exactly where quotes and newlines show up.

Do Not Fix This With Regex

Regex can help find suspicious lines in a controlled file, but it is the wrong tool for repairing arbitrary JSON strings. JSON strings can contain escaped quotes, escaped backslashes, Unicode escapes, and braces that are just characters.

This string is valid JSON:

{
  "message": "brace } quote \" backslash \\ newline \n"
}

A simple regex that looks for the next " or } will get this wrong. Use a JSON parser for validation and a serializer for generation. Use a repair parser only for human-pasted examples where someone will review the output.

A Safer Generation Pattern

Most unterminated string bugs disappear when JSON is treated as data, not as a template language.

Bad:

function makePayload(name, note) {
  return '{ "name": "' + name + '", "note": "' + note + '" }';
}

Good:

function makePayload(name, note) {
  return JSON.stringify({ name, note });
}

If the receiving API needs pretty output for debugging:

const json = JSON.stringify({ name, note }, null, 2);

If the string came from a file, parse it once at the boundary and keep the parsed value as an object inside your application. Do not parse, stringify, concatenate, and parse again unless there is a clear contract reason.

Repair or Reject?

The right response depends on where the broken JSON came from.

Source Recommended action
Copied example in a support ticket Repair locally, then review the repaired value
LLM-generated JSON Repair only if the missing quote is obvious; still validate fields after parsing
Hand-edited config Fix the quote, then commit the corrected JSON with a test or formatter check
API response Reject and fix the producer; do not guess missing data
Webhook or payment payload Reject, log safe metadata, and request a retry
Streaming response Wait for the full stream or implement proper framing before parsing

Adding a quote at the end may make the parser happy, but it can invent data that never arrived. That is fine for a toy snippet. It is not fine for permissions, orders, migrations, payments, or audit logs.

A Practical Debugging Checklist

  1. Copy the exact failing text into a local scratch file, redacting secrets first.
  2. Use the parser's position, line, or column to find the string that opened.
  3. Check whether the closing quote is missing or escaped.
  4. Search inside the value for raw newlines, tabs, and unescaped quotes.
  5. If the input ends abruptly, check transport, file, or stream truncation before editing the JSON.
  6. Replace manual JSON construction with JSON.stringify() or your language's JSON encoder.
  7. Add a regression test using the exact failing shape.

For example:

test("serializes notes with quotes and newlines", () => {
  const note = 'He said "ship it"\nthen left';
  const json = JSON.stringify({ note });

  expect(JSON.parse(json)).toEqual({ note });
});

That test protects against both inner quotes and raw newlines.

Can JSON Fix Help?

JSON Fix can help when you have a pasted snippet, a support-ticket sample, or LLM output that is almost JSON. It can point you toward the string that failed and repair common syntax mistakes in the browser.

For production data, use the tool as a diagnostic aid, not as a contract. If an API response or webhook body arrives with an unterminated string, the producer sent incomplete or invalid data. The durable fix belongs upstream.

For strict checking, use JSON Validator. To inspect the parsed value after repair, use JSON Viewer. If you need to prove the repaired payload did not change meaning, compare before and after with JSON Diff.

Frequently Asked Questions

What causes "Unterminated string in JSON"?

It means a JSON string opened with a double quote but did not close correctly. Common causes are a missing closing quote, a final backslash that escaped the closing quote, a raw newline inside the value, or a response truncated mid-string.

How do I find the unterminated string?

Use the parser's position, line, or column as a clue, then inspect forward from the nearest opening double quote. Look for a missing closing quote, \" where the quote was supposed to close, a raw line break, or an abrupt end of input.

How do I include a quote inside a JSON string?

Escape the inner quote as \", or better, build the JSON with JSON.stringify() so quotes, backslashes, and control characters are escaped by the serializer.

How do I include a newline inside a JSON string?

Use the two-character escape sequence \n inside the JSON text. Do not put a literal line break between the opening and closing quotes. Some parsers report raw newlines as unterminated strings, while others report bad control characters.

Why does a Windows path cause this error?

A path that ends with a single backslash can escape the closing quote, as in C:\\exports\". Escape the final backslash as \\, or pass the path as a normal value to JSON.stringify().

Is this the same as "Unexpected end of JSON input"?

Not exactly. Unterminated string means the parser was inside a string when parsing failed. Unexpected end of JSON input means the whole document ended before a complete value was available. A truncated response can cause either error depending on where it was cut off.

Can JSON Fix repair an unterminated string?

Sometimes, especially for pasted snippets where the missing quote or escaped closing quote is obvious. It should not be used to guess missing production data from APIs, webhooks, payments, or permission-changing workflows.

How do I prevent this in JavaScript?

Stop concatenating JSON strings. Build a JavaScript object and call JSON.stringify(value). For incoming data, wait for the full response or stream before parsing, and log only safe metadata when parse errors happen.

Related Guides

Sources

Last reviewed July 2026.