markupsafe icon indicating copy to clipboard operation
markupsafe copied to clipboard

Python 3.14: SystemError: <built-in function _escape_inner> returned NULL without setting an exception

Open hugovk opened this issue 5 months ago • 1 comments
trafficstars

Environment: macOS Apple silicon

  • Python version: 3.14.0b3
  • MarkupSafe version: 3.0.2
from markupsafe import escape

print(escape(828))

Gives:

❯ python3.14 1.py
Traceback (most recent call last):
  File "/Users/hugo/github/devguide/1.py", line 3, in <module>
    print(escape(828))
          ~~~~~~^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/site-packages/markupsafe/__init__.py", line 45, in escape
    return Markup(_escape_inner(str(s)))
                  ~~~~~~~~~~~~~^^^^^^^^
SystemError: <built-in function _escape_inner> returned NULL without setting an exception

It prints out 828 as expected with:

  • Python 3.14 and MarkupSafe 3.0.1
  • Python 3.13 and MarkupSafe 3.0.1
  • Python 3.13 and MarkupSafe 3.0.2

hugovk avatar Jun 23 '25 14:06 hugovk

I can't reproduce this issue. I installed 3.14.0b3 from python.org, and ran the following:

$ uv run --python /Library/Frameworks/Python.framework/Versions/3.14/bin/python3 --with markupsafe==3.0.2 example.py 
828

Your traceback looks like the bug that was fixed in 3.0.1 and 3.0.2. Are you sure you're on 3.0.2?

davidism avatar Jun 23 '25 15:06 davidism

Still reproducible with the uv command.

And adding a version print:

import sys
from markupsafe import escape

print(sys.version)
print(escape("828"))
❯ uv run --python /Library/Frameworks/Python.framework/Versions/3.14/bin/python3 --with markupsafe==3.0.2 1.py
3.14.0b3 (v3.14.0b3:26d485d1225, Jun 17 2025, 12:48:06) [Clang 16.0.0 (clang-1600.0.26.6)]
Traceback (most recent call last):
  File "/private/tmp/1.py", line 5, in <module>
    print(escape("828"))
          ~~~~~~^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/site-packages/markupsafe/__init__.py", line 40, in escape
    return Markup(_escape_inner(s))
                  ~~~~~~~~~~~~~^^^
SystemError: <built-in function _escape_inner> returned NULL without setting an exception

Same error with:

import sys
import markupsafe

print(sys.version)
print(markupsafe.escape("828"))

And:

import sys
from markupsafe import escape
import markupsafe

print(sys.version)
print(markupsafe.escape("828"))

Hmm, but this works:

import sys
from markupsafe import escape
import markupsafe

print(sys.version)
print(escape("828"))

hugovk avatar Jun 24 '25 07:06 hugovk

All those work for me. Printing the version, and renaming to 1.py:

uv run --python /Library/Frameworks/Python.framework/Versions/3.14/bin/python3 --with markupsafe==3.0.2 1.py
3.14.0b3 (v3.14.0b3:26d485d1225, Jun 17 2025, 12:48:06) [Clang 16.0.0 (clang-1600.0.26.6)]
828

davidism avatar Jun 24 '25 13:06 davidism

I'm on another Mac right now and they also all work here too...

❯ uv run --python /Library/Frameworks/Python.framework/Versions/3.14/bin/python3 --with markupsafe==3.0.2 1.py
3.14.0b3 (v3.14.0b3:26d485d1225, Jun 17 2025, 12:48:06) [Clang 16.0.0 (clang-1600.0.26.6)]
828

hugovk avatar Jun 24 '25 14:06 hugovk

Perhaps uv built and cached a MarkupSafe wheel compiled against a previous 3.14 version. The wheel name would look correct to the installer, but might have incompatible compiled C code. Try running with a different --cache-dir to force it to recompile MarkupSafe.

davidism avatar Jun 24 '25 14:06 davidism

Thanks, it was indeed some old cached files. Comparing the problematic machine (left) with the working one (right) shows files were built in April and May respectively:

Image

And the WHEEL file shows the problematic one was built with an older setuptools giving an older tag:

Image

(--cache-dir and --no-cache didn't actually help, I instead did a full uv cache clean)

Thanks again for the help!

hugovk avatar Jun 24 '25 18:06 hugovk