import functools
p = functools.partial(print)
p.keywords[1] = 'x'
p()
type_call() does not validate kwargs contents, passing them through to tp_new/tp_init as-is. Most of the time, PyArg_ParseTupleAndKeywords gets run pretty soon, and this catches any non-str keywords, but if for any reason this doesn't happen, then we get non-str keywords in places that assume all keywords are str.
frame #4: 0x0000fffff7d413ac libc.so.6`__assert_fail + 204
frame #5: 0x0000aaaaab398170 python3`find_keyword(kwnames=0x0000fffff7200190, kwstack=0x0000ffffffffbb70, key=0x0000aaaaab7d51b0) at getargs.c:2271:9
frame #6: 0x0000aaaaab3995c0 python3`_PyArg_UnpackKeywords(args=0x0000ffffffffbb70, nargs=0, kwargs=0x0000000000000000, kwnames=<unavailable>, parser=<unavailable>, minpos=0, maxpos=0, minkw=0, varpos=1, buf=0x0000ffffffffb958) at getargs.c:2636:31
frame #7: 0x0000aaaaab267120 python3`builtin_print(module=0x0000fffff7c60200, args=0x0000ffffffffbb70, nargs=0, kwnames=0x0000fffff7200190) at bltinmodule.c.h:1094:16
frame #8: 0x0000aaaaaafe9850 python3`cfunction_vectorcall_FASTCALL_KEYWORDS(func=0x0000fffff7c56f30, args=0x0000ffffffffbb70, nargsf=0, kwnames=0x0000fffff7200190) at methodobject.c:465:24
frame #9: 0x0000aaaaab6e4d28 python3`_PyObject_VectorcallTstate(tstate=0x0000aaaaab7f98e0, callable=0x0000fffff7c56f30, args=0x0000ffffffffbb70, nargsf=0, kwnames=0x0000fffff7200190) at pycore_call.h:144:11
frame #10: 0x0000aaaaab6e42a8 python3`partial_vectorcall(self=0x0000fffff71b09d0, args=<unavailable>, nargsf=<unavailable>, kwnames=0x0000000000000000) at _functoolsmodule.c:555:14
frame #11: 0x0000aaaaaaeb0b64 python3`_PyObject_VectorcallTstate(tstate=0x0000aaaaab7f98e0, callable=0x0000fffff71b09d0, args=0x0000ffffffffbcd0, nargsf=9223372036854775808, kwnames=0x0000000000000000) at pycore_call.h:144:11
frame #12: 0x0000aaaaab2d7d64 python3`PyObject_Vectorcall(callable=<unavailable>, args=0x0000ffffffffbcd0, nargsf=<unavailable>, kwnames=0x0000000000000000) at call.c:327:12 [inlined]
frame #13: 0x0000aaaaab2d7d54 python3`_Py_VectorCallInstrumentation_StackRefSteal(callable=<unavailable>, arguments=0x0000fffff7fe94a8, total_args=<unavailable>, kwnames=(bits = 1), call_instrumentation=false, frame=0x0000fffff7fe9448, this_instr=0x0000fffff7c5c378, tstate=0x0000aaaaab7f98e0) at ceval.c:768:11
frame #14: 0x0000aaaaab28436c python3`_PyEval_EvalFrameDefault(tstate=<unavailable>, frame=<unavailable>, throwflag=<unavailable>) at generated_cases.c.h:1906:35
frame #15: 0x0000aaaaab270f54 python3`_PyEval_EvalFrame(tstate=0x0000aaaaab7f98e0, frame=0x0000fffff7fe9448, throwflag=0) at pycore_ceval.h:122:16 [inlined]
frame #16: 0x0000aaaaab270f2c python3`_PyEval_Vector(tstate=<unavailable>, func=<unavailable>, locals=0x0000fffff7acd610, args=<unavailable>, argcount=<unavailable>, kwnames=0x0000000000000000) at ceval.c:2172:12
frame #17: 0x0000aaaaab2708f0 python3`PyEval_EvalCode(co=0x0000fffff7c5c280, globals=0x0000fffff7acd610, locals=0x0000fffff7acd610) at ceval.c:679:21
frame #18: 0x0000aaaaab262c38 python3`builtin_exec_impl(module=<unavailable>, source=0x0000fffff7c5c280, globals=0x0000fffff7acd610, locals=0x0000fffff7acd610, closure=<unavailable>) at bltinmodule.c:1267:17
frame #19: 0x0000aaaaab2629b0 python3`builtin_exec(module=<unavailable>, args=0x0000ffffffffcf98, nargs=<unavailable>, kwnames=0x0000000000000000) at bltinmodule.c.h:676:20
frame #20: 0x0000aaaaab2da030 python3`_Py_BuiltinCallFastWithKeywords_StackRef(callable=(bits = 281474838652656), arguments=0x0000fffff7fe9438, total_args=2) at ceval.c:841:11
frame #21: 0x0000aaaaab288600 python3`_PyEval_EvalFrameDefault(tstate=<unavailable>, frame=<unavailable>, throwflag=<unavailable>) at generated_cases.c.h:2603:35
frame #22: 0x0000aaaaab270f54 python3`_PyEval_EvalFrame(tstate=0x0000aaaaab7f98e0, frame=0x0000fffff7fe9020, throwflag=0) at pycore_ceval.h:122:16 [inlined]
frame #23: 0x0000aaaaab270f2c python3`_PyEval_Vector(tstate=<unavailable>, func=<unavailable>, locals=0x0000000000000000, args=<unavailable>, argcount=<unavailable>, kwnames=0x0000fffff77962d0) at ceval.c:2172:12
frame #24: 0x0000aaaaaaeb31d0 python3`_PyVectorcall_Call(tstate=0x0000aaaaab7f98e0, func=<unavailable>, callable=0x0000fffff71cb890, tuple=0x0000aaaaab7da228, kwargs=0x0000fffff71c43b0) at call.c:285:24
frame #25: 0x0000aaaaab526178 python3`PyObject_Call(callable=0x0000fffff71cb890, args=<unavailable>, kwargs=0x0000fffff71c43b0) at call.c:373:12 [inlined]
I wasn't sure wether to raise one or two issues here, as I think it's likely that there will have to be two fixes at the individual call sites, but they're the same underlying problem.
As the functools.partial call actually calls the wrapped function with the bad argument names, there are a few functions that get tripped up here:
>>> functools.partial(enumerate, **{1: None})([])
Objects/unicodeobject.c:606: _PyUnicode_CheckConsistency: Assertion failed: PyType_HasFeature((_Py_TYPE_impl(((PyObject*)((op))))), ((1UL << 28)))
Enable tracemalloc to get the memory block allocation traceback
object address : 0x100e94800
object refcount : 3221225472
object type : 0x100e5ec80
object type name: int
object repr : 1
Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized
Current thread 0x00000002051c7b40 (most recent call first):
File "<python-input-2>", line 1 in <module>
File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/console.py", line 235 in runcode
File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/console.py", line 292 in runsource
File "/Users/sstagg/src/tp/cpython/Lib/code.py", line 324 in push
File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/simple_interact.py", line 151 in run_multiline_interactive_console
File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/main.py", line 58 in interactive_console
fish: Job 1, './python.exe' terminated by signal SIGABRT (Abort)
Python 3.16.0a0 (heads/main:9f878002205, Aug 13 2026, 15:07:54) [Clang 21.0.0 (clang-2100.3.27.1)]
Crash report
What happened?
and
also:
type_call() does not validate kwargs contents, passing them through to tp_new/tp_init as-is. Most of the time, PyArg_ParseTupleAndKeywords gets run pretty soon, and this catches any non-str keywords, but if for any reason this doesn't happen, then we get non-str keywords in places that assume all keywords are str.
Partial Stackframe #4: 0x0000fffff7d413ac libc.so.6`__assert_fail + 204 frame #5: 0x0000aaaaab398170 python3`find_keyword(kwnames=0x0000fffff7200190, kwstack=0x0000ffffffffbb70, key=0x0000aaaaab7d51b0) at getargs.c:2271:9 frame #6: 0x0000aaaaab3995c0 python3`_PyArg_UnpackKeywords(args=0x0000ffffffffbb70, nargs=0, kwargs=0x0000000000000000, kwnames=<unavailable>, parser=<unavailable>, minpos=0, maxpos=0, minkw=0, varpos=1, buf=0x0000ffffffffb958) at getargs.c:2636:31 frame #7: 0x0000aaaaab267120 python3`builtin_print(module=0x0000fffff7c60200, args=0x0000ffffffffbb70, nargs=0, kwnames=0x0000fffff7200190) at bltinmodule.c.h:1094:16 frame #8: 0x0000aaaaaafe9850 python3`cfunction_vectorcall_FASTCALL_KEYWORDS(func=0x0000fffff7c56f30, args=0x0000ffffffffbb70, nargsf=0, kwnames=0x0000fffff7200190) at methodobject.c:465:24 frame #9: 0x0000aaaaab6e4d28 python3`_PyObject_VectorcallTstate(tstate=0x0000aaaaab7f98e0, callable=0x0000fffff7c56f30, args=0x0000ffffffffbb70, nargsf=0, kwnames=0x0000fffff7200190) at pycore_call.h:144:11 frame #10: 0x0000aaaaab6e42a8 python3`partial_vectorcall(self=0x0000fffff71b09d0, args=<unavailable>, nargsf=<unavailable>, kwnames=0x0000000000000000) at _functoolsmodule.c:555:14 frame #11: 0x0000aaaaaaeb0b64 python3`_PyObject_VectorcallTstate(tstate=0x0000aaaaab7f98e0, callable=0x0000fffff71b09d0, args=0x0000ffffffffbcd0, nargsf=9223372036854775808, kwnames=0x0000000000000000) at pycore_call.h:144:11 frame #12: 0x0000aaaaab2d7d64 python3`PyObject_Vectorcall(callable=<unavailable>, args=0x0000ffffffffbcd0, nargsf=<unavailable>, kwnames=0x0000000000000000) at call.c:327:12 [inlined] frame #13: 0x0000aaaaab2d7d54 python3`_Py_VectorCallInstrumentation_StackRefSteal(callable=<unavailable>, arguments=0x0000fffff7fe94a8, total_args=<unavailable>, kwnames=(bits = 1), call_instrumentation=false, frame=0x0000fffff7fe9448, this_instr=0x0000fffff7c5c378, tstate=0x0000aaaaab7f98e0) at ceval.c:768:11 frame #14: 0x0000aaaaab28436c python3`_PyEval_EvalFrameDefault(tstate=<unavailable>, frame=<unavailable>, throwflag=<unavailable>) at generated_cases.c.h:1906:35 frame #15: 0x0000aaaaab270f54 python3`_PyEval_EvalFrame(tstate=0x0000aaaaab7f98e0, frame=0x0000fffff7fe9448, throwflag=0) at pycore_ceval.h:122:16 [inlined] frame #16: 0x0000aaaaab270f2c python3`_PyEval_Vector(tstate=<unavailable>, func=<unavailable>, locals=0x0000fffff7acd610, args=<unavailable>, argcount=<unavailable>, kwnames=0x0000000000000000) at ceval.c:2172:12 frame #17: 0x0000aaaaab2708f0 python3`PyEval_EvalCode(co=0x0000fffff7c5c280, globals=0x0000fffff7acd610, locals=0x0000fffff7acd610) at ceval.c:679:21 frame #18: 0x0000aaaaab262c38 python3`builtin_exec_impl(module=<unavailable>, source=0x0000fffff7c5c280, globals=0x0000fffff7acd610, locals=0x0000fffff7acd610, closure=<unavailable>) at bltinmodule.c:1267:17 frame #19: 0x0000aaaaab2629b0 python3`builtin_exec(module=<unavailable>, args=0x0000ffffffffcf98, nargs=<unavailable>, kwnames=0x0000000000000000) at bltinmodule.c.h:676:20 frame #20: 0x0000aaaaab2da030 python3`_Py_BuiltinCallFastWithKeywords_StackRef(callable=(bits = 281474838652656), arguments=0x0000fffff7fe9438, total_args=2) at ceval.c:841:11 frame #21: 0x0000aaaaab288600 python3`_PyEval_EvalFrameDefault(tstate=<unavailable>, frame=<unavailable>, throwflag=<unavailable>) at generated_cases.c.h:2603:35 frame #22: 0x0000aaaaab270f54 python3`_PyEval_EvalFrame(tstate=0x0000aaaaab7f98e0, frame=0x0000fffff7fe9020, throwflag=0) at pycore_ceval.h:122:16 [inlined] frame #23: 0x0000aaaaab270f2c python3`_PyEval_Vector(tstate=<unavailable>, func=<unavailable>, locals=0x0000000000000000, args=<unavailable>, argcount=<unavailable>, kwnames=0x0000fffff77962d0) at ceval.c:2172:12 frame #24: 0x0000aaaaaaeb31d0 python3`_PyVectorcall_Call(tstate=0x0000aaaaab7f98e0, func=<unavailable>, callable=0x0000fffff71cb890, tuple=0x0000aaaaab7da228, kwargs=0x0000fffff71c43b0) at call.c:285:24 frame #25: 0x0000aaaaab526178 python3`PyObject_Call(callable=0x0000fffff71cb890, args=<unavailable>, kwargs=0x0000fffff71c43b0) at call.c:373:12 [inlined]I wasn't sure wether to raise one or two issues here, as I think it's likely that there will have to be two fixes at the individual call sites, but they're the same underlying problem.
Additional context
As the functools.partial call actually calls the wrapped function with the bad argument names, there are a few functions that get tripped up here:
for example:
>>> functools.partial(enumerate, **{1: None})([]) Objects/unicodeobject.c:606: _PyUnicode_CheckConsistency: Assertion failed: PyType_HasFeature((_Py_TYPE_impl(((PyObject*)((op))))), ((1UL << 28))) Enable tracemalloc to get the memory block allocation traceback object address : 0x100e94800 object refcount : 3221225472 object type : 0x100e5ec80 object type name: int object repr : 1 Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed Python runtime state: initialized Current thread 0x00000002051c7b40 (most recent call first): File "<python-input-2>", line 1 in <module> File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/console.py", line 235 in runcode File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/console.py", line 292 in runsource File "/Users/sstagg/src/tp/cpython/Lib/code.py", line 324 in push File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/simple_interact.py", line 151 in run_multiline_interactive_console File "/Users/sstagg/src/tp/cpython/Lib/_pyrepl/main.py", line 58 in interactive_console fish: Job 1, './python.exe' terminated by signal SIGABRT (Abort)CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.16.0a0 (heads/main:9f878002205, Aug 13 2026, 15:07:54) [Clang 21.0.0 (clang-2100.3.27.1)]
Linked PRs