Unterminated string in JSON: How to Fix It in PHP
Unterminated string in JSON means a string opened with a quote and never closed. In PHP, json_decode reports it as Syntax error. Find the missing quote…
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →Unterminated string in JSON means a string opened with a double quote and the text ended before a closing quote appeared. PHP's json_decode reports this as a plain Syntax error, so you have to find the open string yourself.
What “Unterminated string in JSON” means
The parser found an opening double quote and never found the matching closing one. The JSON standard says a string starts and ends with a double quote, so a string with no end is not valid JSON. PHP does not print the words unterminated string. json_decode returns null, json_last_error_msg() returns Syntax error, and with JSON_THROW_ON_ERROR you get a JsonException with the same text. The phrase itself comes from other parsers, such as the one in JavaScript, or from a tool that reads your payload.
Causes and the fix for each
A closing quote is missing from a hand-built string.
Someone assembled the JSON with string concatenation or a template and left out the quote that ends a value. The parser keeps reading the rest of the text as part of that string until the input ends. This is common in code that builds JSON from pieces instead of encoding an array.
Before (fails):{"name": "Ada}
After (valid):
{"name": "Ada"}
A trailing backslash escapes the closing quote.
In JSON a backslash followed by a quote means a literal quote character inside the string. A Windows path that ends in a single backslash therefore swallows the closing quote. The string then runs to the end of the text. Each literal backslash must be written as two.
Before (fails):{"path": "C:\temp\"}
After (valid):
{"path": "C:\\temp\\"}
The payload was cut off in transit.
An HTTP response that stops early, a curl timeout, or a dropped connection can leave you with only the first part of the body. If the cut falls inside a string value, the closing quote never arrives. The text looks fine at the start and ends mid-word.
Before (fails):{"bio": "Writes about PH
After (valid):
{"bio": "Writes about PHP"}
Stored JSON was truncated by a length limit.
A database column that is too short, or a call to substr or mb_substr on the encoded JSON, can chop the text in the middle of a value. Depending on the database mode, the cut may happen without any error. You then read back JSON that ends inside a string.
Before (fails):{"text": "Hello wor
After (valid):
{"text": "Hello world"}
A curly quote was used where a straight quote belongs.
Text copied from a document editor or chat tool often carries typographic quotes. JSON only accepts the plain double quote as a string delimiter. A curly quote is treated as an ordinary character, so the string stays open past it.
Before (fails):{"name": "Ada”}
After (valid):
{"name": "Ada"}
How to fix it in PHP
- Decode with JSON_THROW_ON_ERROR and catch JsonException. The message will be Syntax error, which confirms the text is invalid but does not say where. Treat that as the signal to inspect the string.
- Look at the raw text. Log the start and the end of the string you pass to json_decode. If the end stops in the middle of a word or a value, the data was cut off. If the end looks complete, search for a stray quote or a trailing backslash.
- Trace where the string came from. Check the HTTP status and any curl timeout, the size of the database column that stored it, and any substr or mb_substr call applied to the JSON text.
- Stop building JSON by hand. Put the data in a PHP array or object and call json_encode, which escapes quotes and backslashes for you. Check for a false return as well.
- Paste the broken text into the Repair tool to close the open string and see what was missing. Use the Validator afterwards to confirm the result parses, and the Formatter to read it.
- Fix the source of the bad text, not only the copy you repaired. A repaired payload that was truncated may be missing data, so request it again when you can.
<?php
function safeDecode(string $raw): ?array
{
try {
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
error_log('JSON decode failed: ' . $e->getMessage());
error_log('Start: ' . substr($raw, 0, 100));
error_log('End: ' . substr($raw, -100));
return null;
}
return is_array($data) ? $data : null;
}
$result = safeDecode('{"name": "Ada}');
if ($result === null) {
// Retry the request or send the text to a repair step.
}
Variants of the message
| Message | Cause | Fix |
|---|---|---|
| Syntax error (PHP json_last_error_msg) | Any invalid JSON, including a string with no closing quote | Inspect the end of the raw text and look for a missing quote |
| Unterminated string in JSON at position N (JavaScript) | A string opened and the input ended before it closed | Go to the reported position and add the closing quote |
| Unterminated string starting at (Python) | The same open string, reported by Python's json module | Check the character offset in the message and close the string |
| Unexpected end of JSON input (JavaScript) | The text was cut off, often outside a string | Check for a truncated response or a short database column |
| Control character error, possible incorrect encoding (PHP) | A raw newline or tab sits inside a string value | Escape control characters, or build the text with json_encode |
| Malformed UTF-8 characters, possibly incorrectly encoded (PHP) | Invalid bytes in the text, sometimes left by a mid-character cut | Convert to UTF-8 before decoding and avoid byte-wise substr on JSON |
Related errors
- Invalid JSON Meaning: What It Is and How to Fix It
- JavaScript JSON.parse() Errors: What They Mean and How to Fix Them
- Invalid control character in JSON: How to Fix It in Python
- Invalid escape sequence in JSON: How to Fix It in Python
- JSONDecodeError: Expecting ',' delimiter: How to Fix It in Python
Key takeaways
- Unterminated string means a string opened and the text ended before its closing quote.
- PHP reports it as Syntax error, with no position.
- Common causes are a missing quote, a trailing backslash, curly quotes and truncated data.
- Build JSON with json_encode instead of string concatenation.
- Check the end of the raw text first, then use the Repair tool or the Validator.
FAQ
Why does PHP say Syntax error and not Unterminated string?
PHP's json_decode uses one general error code for most malformed input. It returns Syntax error and does not name the exact problem or give a position. Other parsers, such as JavaScript's, use more specific messages.
Can json_decode tell me the position of the error?
No. json_last_error_msg and JsonException give a message but no offset. To find the position, check the end of the string first, then run the text through the Validator, which can point at the location.
Is a truncated response the same as an unterminated string?
A truncated response is one common cause. If the cut falls inside a string value, the parser reports an open string. If it falls elsewhere, you may get a different message.
Can a repair tool recover the lost data?
No. A repair tool can close the string and the brackets so the text parses, but it cannot restore characters that were never received or were cut off. Request the data again when completeness matters.
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