Skip to content

[BUG] except* in async def, generators, at module level or in module-level class bodies generates C that doesn't compile (__pyx_skip_add_traceback undeclared) #8043

Open

Description

@bwenstar

Describe the bug

except* (new in 3.3.0) works in a normal function, but in async def, generators, at module level and in module-level class bodies, Cython generates C that uses __pyx_skip_add_traceback without declaring it. Cython itself reports no error; the C compiler fails:

error: '__pyx_skip_add_traceback' undeclared (first use in this function); did you mean '__Pyx_AddTraceback'?
except* inside Result
def compiles and works
async def C compile error
generator (def with yield) C compile error
async generator C compile error
module level C compile error
class body (at module level) C compile error
class body inside a def compiles and works

FuncDefNode.generate_function_definitions declares the variable. GeneratorBodyDefNode overrides that method without the declaration, and the module init function doesn't declare it either.

Code to reproduce the behaviour:

t.py:

async def f():
    try:
        raise ExceptionGroup("g", [ValueError()])
    except* ValueError:
        r = "caught"
    return r
cython -3 t.py -o t.c
gcc -O2 -shared -fPIC $(python3-config --includes) t.c -o t$(python3-config --extension-suffix)

cython succeeds and gcc fails with the error above. Changing async def to def (and calling it normally) compiles and works.

Expected behaviour

The module compiles, and asyncio.run(t.f()) returns "caught", the same as pure Python.

OS

Ubuntu 24.04, x86_64, gcc 13.3

Python version

3.12.3

Cython version

3.3.0 (master's Nodes.py still only declares the variable in FuncDefNode)

Additional context

Declaring the variable in GeneratorBodyDefNode the same way FuncDefNode does fixes async def, generators and async generators. This is the change I tested:

--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -5005,6 +5005,9 @@
 
             for cname, type in code.funcstate.all_managed_temps():
                 code.put_xdecref(cname, type)
+            if code.funcstate.has_except_star:
+                tempvardecl_code.putln(
+                    f"int {Naming.skip_add_traceback_cname} = 0;")
             code.putln("if (__Pyx_PyErr_Occurred()) {")  # we allow exit without GeneratorExit / StopIteration
             if tracing:
                 code.put_trace_exception_propagating()

except* at module level, or in a module-level class body, still fails with this change. Those cases need the same declaration in the module init function.

Activity

  1. matusvalo commented on Oct 12, 2026

    @matusvalo
    Contributor

    I confirm the bug and fix. Thank you @bwenstar !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions