Formatter Validator Minifier Escape / Unescape JSON ↔ String JSON ↔ YAML JSON → CSV NDJSON / JSON Lines JSON → Types JSON ↔ XML JSON Diff JSON Patch Canonicalize (RFC 8785) Schema Validator Schema Generator JSONPath Tester JWT Decoder JSON Errors Schemas More Tools
JSONTools / JSON errors / Lone surrogate in a JSON string
JSON error registry · String content

Lone surrogate in a JSON string

A high surrogate (`\uD800`–`\uDBFF`) with no following low surrogate. Characters outside the Basic Multilingual Plane — emoji, most notably — are encoded as a surrogate pair, and splitting a string by UTF-16 code unit can cut one in half.

The input

Fails to parse
{"a": "\uD800"}
Parses correctly
{"a": "\uD83D\uDE00"}

Open this broken input in the formatter →

How to fix it

Never slice strings on UTF-16 boundaries. Slice by code point, or by grapheme cluster if you care about emoji sequences.

Parsers disagree here: some accept a lone surrogate and produce a replacement character, others reject it. That inconsistency makes this bug travel a long way before anyone notices.

What each parser reports

Every message below was captured by running this exact input through the parser named. 5 of 21 parsers rejected it; 16 accepted it.

Parser Exact message
CPython json.loads
CPython 3.12.3
accepted — no error
encoding/json Unmarshal
Go go1.22.2
accepted — no error
Gson
Java 21.0.12
accepted — no error
Gson JsonParser (lenient off)
Java 21.0.12
accepted — no error
hjson
Node.js 22.22.2
accepted — no error
Jackson ObjectMapper
Java 21.0.12
accepted — no error
JavaScriptCore JSON.parse
JavaScriptCore (Bun 1.4.1)
accepted — no error
json-bigint
Node.js 22.22.2
accepted — no error
JSON5
Node.js 22.22.2
accepted — no error
JSON::PP
Perl 5.038002
missing low surrogate character in surrogate pair, at character offset 15 (before "(end of string)")
what this message means →
json_decode
PHP 8.3.6
Single unpaired UTF-16 surrogate in unicode escape
what this message means →
Newtonsoft.Json JsonConvert
Newtonsoft.Json 13.0.3 on .NET 8.0.30
accepted — no error
Newtonsoft.Json JsonTextReader
Newtonsoft.Json 13.0.3 on .NET 8.0.30
accepted — no error
orjson
CPython 3.12.3
no low surrogate in string: line 1 column 8 (char 7)
what this message means →
Ruby JSON.parse
Ruby 3.2.3
incomplete surrogate pair at '\uD800"}'
what this message means →
serde_json::from_str
Rust (serde_json 1.x)
unexpected end of hex escape at line 1 column 14
what this message means →
SpiderMonkey JSON.parse
SpiderMonkey 115
accepted — no error
System.Text.Json Deserialize
.NET 8.0.30
accepted — no error
System.Text.Json JsonDocument
.NET 8.0.30
accepted — no error
ujson
CPython 3.12.3
accepted — no error
V8 JSON.parse
Node.js 22.22.2
accepted — no error

What the specification says

The exact sections that govern this error. Descriptions are our paraphrase; follow the links for the normative text.

Body Section
IETF
A string begins and ends with a quotation mark. Any Unicode character may appear between them except the quotation mark, the reverse solidus, and the control characters U+0000 through U+001F, which the section requires to be escaped. It also fixes the escape set and the \uXXXX form.
IETF
The section notes the grammar permits bit sequences that are not Unicode characters, gives an unpaired surrogate as its example, and describes the behaviour of receiving software as unpredictable.
Ecma International
A string is code points wrapped in quotation marks; the quotation mark, reverse solidus and U+0000–U+001F must be escaped. Table 3 fixes the escape sequences.
Unicode Consortium
Normatively referenced by RFC 8259 for the definition of a character.
IETF
The encoding RFC 8259 §8.1 requires for JSON exchanged between systems.

Other errors in this category

Literal newline inside a JSON string

A real line break between the quotes. JSON forbids unescaped control characters (U+0000 to U+001F) inside strings, and a newline i…

Literal tab inside a JSON string

A raw tab character inside string content. Like a newline, it is a control character and must be escaped.…

Invalid escape sequence in a JSON string

A backslash followed by a character JSON does not define. The complete set is `\" \\ \/ \b \f \n \r \t` and `\uXXXX`. Windows path…

Malformed \u escape in a JSON string

A `\u` not followed by exactly four hexadecimal digits.…

Truncated \u escape in a JSON string

A `\u` escape with fewer than four hex digits, typically where a string was cut mid-escape by a length limit.…

Raw NUL byte inside a JSON string

A U+0000 byte in string content, usually from a C string boundary, a fixed-width database column, or binary data that was treated …

← All JSON parser errors