Skip to main content

Python/errors.c

Source:

cpython 3.14 @ ab2d84fe1023/Python/errors.c

Python/errors.c is the low-level exception API. All C extension code and the interpreter itself sets, clears, and fetches exceptions through this file.

Map

LinesSymbolRole
1-200PyErr_SetObject, PyErr_SetStringSet current exception
201-400PyErr_Occurred, PyErr_Clear, PyErr_FetchQuery and clear
401-700PyErr_Format, _PyErr_FormatFromCauseFormatted messages
701-1000PyErr_SetExcInfo, _PyErr_StackItemException stack (per-frame)
1001-1300_PyErr_ChainExceptions, PyException_SetCauseChaining (raise X from Y)
1301-1800PyErr_WriteUnraisable, PyErr_PrintLast-resort error output

Reading

Setting an exception

// CPython: Python/errors.c:78 PyErr_SetObject
void
PyErr_SetObject(PyObject *exception, PyObject *value)
{
PyThreadState *tstate = _PyThreadState_GET();
Py_XINCREF(exception);
Py_XINCREF(value);
_PyErr_Restore(tstate, exception, value, NULL);
}

_PyErr_Restore stores the three exception components (type, value, traceback) into tstate->exc_state. The eval loop checks tstate->curexc_type after every opcode that can raise.

PyErr_Format

// CPython: Python/errors.c:445 PyErr_Format
PyObject *
PyErr_Format(PyObject *exception, const char *format, ...)
{
va_list vargs;
va_start(vargs, format);
PyObject *string = PyUnicode_FromFormatV(format, vargs);
va_end(vargs);
PyErr_SetObject(exception, string);
Py_XDECREF(string);
return NULL;
}

Always returns NULL so callers can write return PyErr_Format(...) directly.

Exception chaining

// CPython: Python/errors.c:1080 _PyErr_ChainExceptions
void
_PyErr_ChainExceptions(PyObject *typ, PyObject *val, PyObject *tb)
{
/* Attach the currently-set exception as __context__ of val */
PyObject *cur_typ, *cur_val, *cur_tb;
PyErr_Fetch(&cur_typ, &cur_val, &cur_tb);
...
PyException_SetContext(val, cur_val);
PyErr_Restore(typ, val, tb);
}

This implements the implicit chaining (raise X inside an except block sets X.__context__). Explicit chaining (raise X from Y) calls PyException_SetCause instead.

Unraisable exceptions

// CPython: Python/errors.c:1620 PyErr_WriteUnraisable
void
PyErr_WriteUnraisable(PyObject *obj)
{
/* Called when an exception occurs in __del__, weakref callbacks,
or other places where exceptions cannot propagate. */
...
PySys_WriteStderr("Exception ignored in: ");
...
}

gopy notes

gopy exception state lives in vm.Frame and vm/eval_unwind.go. PyErr_SetObject maps to setting the Go error on the frame. PyErr_Format maps to fmt.Errorf with a Python exception wrapper in objects/. The exception chaining logic (__context__, __cause__) is implemented in vm/eval_unwind.go for RAISE_VARARGS.