Python version errors — SyntaxError from version gaps

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 verbatim error

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.

Which features tie to which version

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.

Version gap, or just a typo?

Both raise SyntaxError, so it's worth knowing which you're looking at — the fixes are opposite.

  • A version gap points at a whole valid construct — a 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.
  • An ordinary typo points at something genuinely malformed: a missing colon, an unclosed bracket, a stray keyword. The fix is in the file — see the syntax-error note in When your server won't start.

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.

The fix: the version picker

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.

  1. Find the version the feature (or library) needs — the table above, or the library's own docs.
  2. Open Settings, pick that Python version.
  3. Restart. The next start runs on the new interpreter and re-installs your 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.


Next steps

Was this guide helpful?