Deeply nested JSON exceeding a parser's depth limit
Recursive-descent parsers use the call stack for nesting, so past a few hundred levels they either raise a depth error or overflow the stack. Some parsers impose an explicit limit as a denial-of-service defence.
Reproduce it
The input
Fails to parse
[[[[ … 1000 levels … ]]]]Parses correctly
{"items": [1, 2, 3]}
The fix
How to fix it
Flatten the structure. If the depth is legitimate, use a streaming or iterative parser rather than raising the recursion limit.
Deep nesting from untrusted input is a real availability risk. Cap the depth at your API boundary rather than at the parser.
Cross-runtime
What each parser reports
Every message below was captured by running this exact input through the parser named. 8 of 21 parsers rejected it; 13 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 | json text or perl structure exceeds maximum nesting level (max_depth set too low?), at character offset 513 (before "[[[[[[[[[[[[[[[[[[[[...")what this message means → |
| json_decode PHP 8.3.6 | Maximum stack depth exceededwhat this message means → |
| Newtonsoft.Json JsonConvert Newtonsoft.Json 13.0.3 on .NET 8.0.30 | The reader's MaxDepth of 64 has been exceeded. Path '[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]', line 1, position 65.what this message means → |
| Newtonsoft.Json JsonTextReader Newtonsoft.Json 13.0.3 on .NET 8.0.30 | The reader's MaxDepth of 64 has been exceeded. Path '[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]', line 1, position 65.what this message means → |
| orjson CPython 3.12.3 | accepted — no error |
| Ruby JSON.parse Ruby 3.2.3 | nesting of 101 is too deepwhat this message means → |
| serde_json::from_str Rust (serde_json 1.x) | recursion limit exceeded at line 1 column 128what this message means → |
| SpiderMonkey JSON.parse SpiderMonkey 115 | accepted — no error |
| System.Text.Json Deserialize .NET 8.0.30 | The maximum configured depth of 64 has been exceeded. Cannot read next JSON array. Path: $ | LineNumber: 0 | BytePositionInLine: 64.what this message means → |
| System.Text.Json JsonDocument .NET 8.0.30 | The maximum configured depth of 64 has been exceeded. Cannot read next JSON array. LineNumber: 0 | BytePositionInLine: 64.what this message means → |
| ujson CPython 3.12.3 | accepted — no error |
| V8 JSON.parse Node.js 22.22.2 | accepted — no error |
Standards
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 parser must accept every text conforming to the grammar, and the section explicitly permits implementations to limit nesting depth, text size, number range and precision, and string length. |
| MITRE | The weakness class that unbounded JSON nesting depth falls under. |
Peer-reviewed literature
- G. Langdale and D. Lemire, “Parsing gigabytes of JSON per second”, The VLDB Journal, vol. 28, pp. 941–960, 2019. doi:10.1007/s00778-019-00578-5