Only show guides for your app
When "invalid syntax" really means "this feature is from a newer Python" — spot the version-gap crash from match/case and friends, then set the right Python in Settings.
A SyntaxError: invalid syntax on code you're sure is correct is one of Python's most confusing errors — because the code often is correct, just for a newer Python than the one running it. New syntax lands in specific Python versions, and an older interpreter rejects it the instant it reads the file. This guide shows the shape and points you at the version picker in Settings.
| At a glance | |
|---|---|
| Symptom | SyntaxError: invalid syntax on code that looks fine |
| Real cause | A newer-Python feature running on an older Python |
| The fix | Set the Python version in Settings (any plan) |
The match/case statement arrived in Python 3.10. Run it on Python 3.9 and the interpreter stops before your program starts:
File "/home/container/app.py", line 2
match status:
^
SyntaxError: invalid syntax
Python points a caret near the construct it couldn't parse. The message says "invalid syntax," but the code is valid — it's just from a version this interpreter doesn't speak yet.
If your SyntaxError lands on one of these, a version gap is the likely cause:
| Feature | Example | Needs Python |
|---|---|---|
| Structural pattern matching | match x: / case 1: |
3.10+ |
X | Y type unions |
def f(a: int | None) |
3.10+ |
| Exception groups | except* ValueError: |
3.11+ |
| The walrus operator | if (n := len(data)) > 10: |
3.8+ |
| f-strings | f"{name}" |
3.6+ |
The same applies to a library you installed — if a dependency uses newer syntax than your interpreter, its file is the one named in the traceback, not yours.
🎯 Good to know: The default here is Python 3.12, which is recent — so this usually appears only after you switch to an older version, or install a package that expects a newer one.
Both raise SyntaxError, so it's worth knowing which you're looking at — the fixes are opposite.
match, a | in a type hint, an except* — and the code reads correctly to your eye. The fix is the version picker, not the file.Either way the crash happens at load time, before any of your logic runs — Python parses the whole file first, so a single bad line stops the program before it starts. That's why the traceback names a line number and nothing from your program has printed yet.
Python version switching lives on the Settings page (the runtime/Docker-image dropdown), on any plan. Versions 3.7 through 3.13 are selectable; the default is 3.12.
requirements.txt against it.⚠️ Heads up: It cuts both ways. A library that only supports up to, say, 3.11 can break on 3.13. When a package documents a supported range, pick a version inside it rather than always reaching for the newest.
Which feature belongs to which release is standard Python, documented in the "What's New" pages at python.org — that's the authority when you need to check a version boundary.