Version 0.22.0 (2026-09-29)
- BREAKING: Setting
gc=Falseon a struct type that has a weakref slot,
whether fromweakref=Trueor from a base class, now raisesValueError.
On CPython 3.12 and later the weakref slot is stored in a pre-header in
front of the instance, so releasing an instance of agc=Falsetype with
that slot corrupted memory, in most builds crashing the interpreter
outright. The combination worked on 3.10 and 3.11, and the restriction
applies there as well, so that the same class definition behaves the same
way on every supported version (#1207). - Add
frozendictsupport on Python 3.15+ (#1052, #1105). - Support passing a callable as
decimal_formattomsgspec.json.Encoderand
msgspec.msgpack.Encoderfor customDecimalencoding (#978). - Support
Literal[True]andLiteral[False]types (#1004). - Publish CPython 3.15 wheels, including freethreaded builds (#1152).
- Publish Linux
riscv64wheels (#987). - Support the PyEmscripten (Pyodide) platform (#1083).
- Fix handling of PEP 695 type parameter syntax (
class Foo[T]) and of
types.GenericAliasinstances in type annotations (#962). - Fix
NameErrorwhen creating aStructwith an unquoted forward
reference on Python 3.14 (#1165). - Fix a crash on incorrect
typing.ClassVarannotations (#1097). - Fix an
AttributeErrorwhen converting to aStructtype defined in a
namespace without a__name__(#1072). - Fix overriding an inherited field alias back to the field's own name
(#1133). - Raise
ValidationErrorinstead ofSystemErrorwhenconvertreceives an
out-of-rangeintfor afloattarget (#1162). - Report
rawrather than the misleadinganyas the expected type when a
non-Rawvalue is given for aRawfield inconvert, and therefore in
yaml.decodeandtoml.decode(#1169). - Fix an empty expected-type name in validation errors for a required
Raw
field in aTypedDict, or aRawfield with adefault_factoryon a
dataclassor anattrsclass (#1176). - Correct the error messages for out-of-range
Metalength bounds
(#1172). - Fix a reference leak when decoding msgpack
Extpayloads (#1109). - Fix backing type declaration of
Ext.code(#1135). - Fix a reference leak in
msgspec.to_builtins, and therefore in
yaml.encode, forarray_like=Truestructs (#1177). - Fix reference leaks in
typenode_collect_literal,Meta.__rich_repr__,
ms_decode_bigint, andEncoder.__init__(#1021, #1022,
#1023, #1040). - Fix
msgspec.inspect.type_infoandmsgspec.json.schemacrashing on mixed-typeLiterals such asLiteral[1, None](#1080). - Place
nulllast in theanyOfgenerated for optional unions in JSON
schemas (#1028). - Fix
minItemsin the JSON schema forarray_like=Truestructs whose fields
are all optional (#1124). - Use
[]or""rather than a Pythonsetorbytearrayobject as the
JSON schemadefaultforStructfields with asetorbytearray
default_factory(#1183). - Preserve JSON Schema metadata and string constraints in
propertyNamesfor
annotated dictionary key types (#866). - Fix
msgspec.json.encoderaisingTypeErrorfor adictkeyed by a plain
enum.Enumwithstrvalues (#1118). - Fix missing GC traversal and clearing of some module state members (#1060).
- Ensure an exception is always set on allocation failures (#1044).
- Fix compilation warnings on Python 3.15 (#1077).
- Report the leading argument of the
encodeanddecodefunctions and
methods as positional-only ininspect.signatureand the rendered docs,
matching runtime behavior (#1116). - Add overloads to the
Metatype stub, so type checkers reject mixinggt
withgeorltwithle(#700). - Many type stub improvements and fixes (#1014, #1043, #1053,
#1055, #1057, #1062, #1063, #1064, #1065,
#1074, #1093, #1114, #1116, #1163, #1173,
#1179). - Document the differences between
msgspec.structs.asdict/astupleand
msgspec.to_builtins(#1025). - Document that
omit_defaultsignores fields with a custom
default_factory(#1076). - Fix the
msgspec.json.decodedocstring to saydec_hookshould raise
NotImplementedErrorfor unsupported types, notTypeError(#774). - msgspec moved to the msgspec GitHub organization;
documentation now lives at msgspec.dev (repository
references updated in #1045).
New Contributors
- @ypnos made their first contribution in #1014
- @sobolevn made their first contribution in #1063
- @gounthar made their first contribution in #987
- @notpushkin made their first contribution in #1103
- @dependabot[bot] made their first contribution in #1106
- @NyanFisher made their first contribution in #978
- @ncoghlan made their first contribution in #813
- @binggao1230 made their first contribution in #1080
- @SarthakB11 made their first contribution in #1028
- @adriangb made their first contribution in #700
- @rvaccone made their first contribution in #1127
- @OPNA2608 made their first contribution in #1135
- @vyrnsynx made their first contribution in #1168
- @STiFLeR7 made their first contribution in #1162
- @Ananthr16 made their first contribution in #1169
- @vzer200 made their first contribution in #1173
- @Yasser-Ameur made their first contribution in #1174
- @fallenmi made their first contribution in #1159
- @dylanpulver made their first contribution in #1163
- @vmphase made their first contribution in #1179
- @Kumzy made their first contribution in #1196
Full Changelog: 0.21.1...0.22.0