Skip to content

gh-69919: Raise SyntaxError for all invalid sources in compile() - #157586

Open
serhiy-storchaka wants to merge 3 commits into
python:mainfrom
serhiy-storchaka:gh-69919-compile-syntaxerror
Open

serhiy-storchaka wants to merge 3 commits into
python:mainfrom
serhiy-storchaka:gh-69919-compile-syntaxerror

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Sep 15, 2026

Copy link
Copy Markdown
Member

compile(), exec(), eval() and ast.parse() now raise SyntaxError instead of ValueError (UnicodeEncodeError) if the source string contains surrogate characters — with the line, column and text of the offending character, like other syntax errors — instead of MemoryError ("Parser stack overflowed") or RecursionError ("Stack overflow during compilation") if the source is too complex to parse or compile, and instead of OverflowError if the source is too large (a line or string literal longer than 231 bytes, or more than 231 lines; verified manually, no tests at that size). This matches how null bytes and undecodable sources are already reported, and means consumers that handle SyntaxErrorcode.InteractiveInterpreter, the REPL, IDLE — need nothing else: IDLE's Shell no longer gets stuck after such input.

Compiling an AST object is unchanged: a cyclic or too deep tree still raises RecursionError, and an out-of-range lineno still raises OverflowError.

The code and codeop documentation no longer mention OverflowError and ValueError "for an invalid literal": that described Python 1.5/2.0 behavior (integer literals too large for a C long, bad escapes in string literals), which has been a SyntaxError since Python 2.4/3.0.

This is an alternative to #157585, which instead makes the consumers catch all exceptions and can be backported.

🤖 Generated with Claude Code

compile(), exec(), eval() and ast.parse() now raise SyntaxError instead
of ValueError if the source string contains surrogate characters, and
instead of MemoryError or RecursionError if the source is too complex
to parse or compile. Consumers that handle SyntaxError, like the code
module and IDLE, no longer need to handle those exceptions.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@serhiy-storchaka

Copy link
Copy Markdown
Member Author

@pablogsal @lysnikolaou This and #157585 are alternatives for the same problem; I would like your opinion on which to take. This one changes the exceptions raised by compile()SyntaxError for surrogates (with a location), for the parser stack overflow (MemoryError today) and for the compiler stack overflow (RecursionError today) — so it is for main only. #157585 instead makes code, _pyrepl and IDLE catch all exceptions from compile(), and can be backported. They can also be combined.

@read-the-docs-community

read-the-docs-community Bot commented Sep 15, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #34577915 | 📁 Comparing 76e5741 against main (82952e3)

  🔍 Preview build  

5 files changed · ± 5 modified

± Modified

A line longer than 2**31 bytes, more than 2**31 lines, or a string
literal longer than 2**31 bytes are syntax errors too. Drop the stale
mentions of OverflowError and ValueError for invalid literals in the
code and codeop documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant