You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
loads() raises RecursionError on legal JSON5 nested just 60 levels deep #150
While fuzzing json5.loads() against the standard library parser, I found that a legal JSON5 document nested just 60 levels deep crashes with RecursionError, while json.loads() handles the same shape to 400+ levels (and beyond).
Minimal repro (Python 3.13, pyjson5 from current main):
So a 120-byte input — quite reachable in real configs (nested schemas, AST-like documents, minified trees) — takes down the call instead of returning a value or a clean ValueError explaining the depth problem. Anyone parsing untrusted JSON5 gets a RecursionError rather than a parse error, which is easy to mishandle.
dumps() has the same flavor of problem, ~332 levels vs 2000+ for json.dumps():
I realize a hand-rolled recursive-descent parser (glop-generated, several frames per grammar level) will inherently use more stack than the C scanner in json — this reads more as "worth a guard rail" than a parsing bug. A couple of options, in case they're useful:
track nesting depth in the parser and fail with a normal ValueError("document nested too deeply") once the remaining stack budget gets thin (i.e., bail out before the interpreter does), or
document the effective depth limit as a known limitation in the README.
Happy to help with either if useful — thanks for the library, and for the fast merges on #141 :)
Yeah, this is a known issue and is (roughly) documented in the README (see the third known issue). I don't document a specific limit because I think the limit depends on the kind of data being parsed. As the note says, I don't think this tends to come up in practice on real (non-synthetic/non-test) data.
I thought about explicitly tracking the depth like you suggest, but I don't think it's worth it; it just turns a standard Python error (RecursionError) into a custom one. In addition, you can work around the standard limit w/ sys.setrecursionlimit if need be.
It's possible I should be a bit more detailed on the note in the README (e.g., give an approximate depth, mention the workaround), though.
You're right — I missed that note in the Known Issues section, mea culpa for not reading the README thoroughly before filing. Fair call on the depth-guard trade-off too: turning a standard RecursionError into a custom error mostly helps the error message, not the caller.
One small data point, take it or leave it: the input that surfaced this for me was machine-generated (an AST-ish document), so it does occasionally bite outside synthetic test data — files like that are where an approximate depth and the sys.setrecursionlimit workaround in that README note would save someone a confused afternoon. But that's just polish, and I appreciate the quick and thoughtful response either way. Closing this out.
Interesting. Good to know that you hit this with real data.
I will add to the readme note. I should probably document this in the docstrings as well ...
Side note: the standard json module used to have more-or-less the same problem, although the level was much higher (something like 1000 levels), but it looks like they must've rewritten it in 3.12 because I haven't seen an upper bound since.
Activity
dpranke commentedon Nov 1, 2026
Yeah, this is a known issue and is (roughly) documented in the README (see the third known issue). I don't document a specific limit because I think the limit depends on the kind of data being parsed. As the note says, I don't think this tends to come up in practice on real (non-synthetic/non-test) data.
I thought about explicitly tracking the depth like you suggest, but I don't think it's worth it; it just turns a standard Python error (RecursionError) into a custom one. In addition, you can work around the standard limit w/
sys.setrecursionlimitif need be.It's possible I should be a bit more detailed on the note in the README (e.g., give an approximate depth, mention the workaround), though.
rahul05ranjan commentedon Nov 1, 2026
You're right — I missed that note in the Known Issues section, mea culpa for not reading the README thoroughly before filing. Fair call on the depth-guard trade-off too: turning a standard
RecursionErrorinto a custom error mostly helps the error message, not the caller.One small data point, take it or leave it: the input that surfaced this for me was machine-generated (an AST-ish document), so it does occasionally bite outside synthetic test data — files like that are where an approximate depth and the
sys.setrecursionlimitworkaround in that README note would save someone a confused afternoon. But that's just polish, and I appreciate the quick and thoughtful response either way. Closing this out.dpranke commentedon Nov 1, 2026
Interesting. Good to know that you hit this with real data.
I will add to the readme note. I should probably document this in the docstrings as well ...
Side note: the standard
jsonmodule used to have more-or-less the same problem, although the level was much higher (something like 1000 levels), but it looks like they must've rewritten it in 3.12 because I haven't seen an upper bound since.