Repository navigation
Description
Description
### Description
On Python 3.14, an unquoted forward reference in a `msgspec.Struct`
field raises `NameError` while the Struct class is being created.
Python 3.14's default deferred-annotation behavior normally permits this
without quoting. The equivalent example using ordinary classes works.
Tested with:
- CPython 3.14.0
- msgspec 0.21.1 (currently the latest release on PyPI)
### Minimal reproducer
```python
import msgspec
class Outer(msgspec.Struct):
inner: Inner
class Inner(msgspec.Struct):
value: int
Actual result
Traceback (most recent call last):
File "<string>", line 6, in <module>
class Outer(msgspec.Struct):
inner: Inner
File "<string>", line 7, in __annotate__
inner: Inner
^^^^^
NameError: name 'Inner' is not defined
Expected result
I expected Outer to be created successfully, with Inner resolved after
the module finishes defining it, as happens with an ordinary Python 3.14
class:
class Outer:
inner: Inner
class Inner:
value: int
assert Outer.__annotations__ == {"inner": Inner}Workarounds
Either of the following prevents the error:
class Outer(msgspec.Struct):
inner: "Inner"or:
from __future__ import annotationsBoth workarounds use stringified annotations instead of Python 3.14's
default deferred-annotation behavior.
Additional context
This appears related to:
- Update annotation parsing to work with PEP 649 in Python 3.14 #651
- PR Fix annotations support on 3.14 #852
PR #852 added Python 3.14 annotation support, but Struct field collection
currently invokes the class annotate function with
annotationlib.Format.VALUE:
Python's annotationlib documentation recommends that metaclasses
inspecting annotations during class construction generally use
Format.FORWARDREF, because names may not yet be resolvable:
Would using Format.FORWARDREF, followed by the existing delayed
forward-reference resolution, be appropriate here?
A practical consequence is that Ruff's UP037 rule considers the explicit
quotes unnecessary on Python 3.14, but removing them can make modules
containing msgspec.Struct schemas fail to import.
Activity
Fix unquoted Struct forward references on Python 3.14 (msgspec#1168)
zyv commentedon Sep 13, 2026
I've also just hit this bug, and it's awesome that it's already fixed in the tree. Thanks @vyrnsynx for working on this. Looking forward to the next release.
Record the merged changes missing from the changelog (msgspec#1195)