python/cpython · critical · RuntimeError

{name!r} was slated for removal after Python {remove_formatt

Error message

{name!r} was slated for removal after Python {remove_formatted} alpha

What it means

Internal CPython helper _deprecated(name, remove=...) (used to retire stdlib APIs) raises RuntimeError when the specified removal version has been reached or passed: either the running version is newer than remove, or it equals remove and the release is past alpha. It exists to make forgotten removals fail loudly in CI rather than silently shipping dead API.

Source

Thrown at Lib/_py_warnings.py:889


_DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}"


def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):
    """Warn that *name* is deprecated or should be removed.

    RuntimeError is raised if *remove* specifies a major/minor tuple older than
    the current Python version or the same version but past the alpha.

    The *message* argument is formatted with *name* and *remove* as a Python
    version tuple (e.g. (3, 11)).

    """
    remove_formatted = f"{remove[0]}.{remove[1]}"
    if (_version[:2] > remove) or (_version[:2] == remove and _version[3] != "alpha"):
        msg = f"{name!r} was slated for removal after Python {remove_formatted} alpha"
        raise RuntimeError(msg)
    else:
        msg = message.format(name=name, remove=remove_formatted)
        _wm.warn(msg, DeprecationWarning, stacklevel=3)


# Private utility function called by _PyErr_WarnUnawaitedCoroutine
def _warn_unawaited_coroutine(coro):
    msg_lines = [
        f"coroutine '{coro.__qualname__}' was never awaited\n"
    ]
    if coro.cr_origin is not None:
        import linecache, traceback
        def extract():
            for filename, lineno, funcname in reversed(coro.cr_origin):
                line = linecache.getline(filename, lineno)
                yield (filename, lineno, funcname, line)
        msg_lines.append("Coroutine created at (most recent call last)\n")
        msg_lines += traceback.format_list(list(extract()))

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. If you maintain a fork/vendor copy of CPython Lib, update the remove= tuple of the offending _deprecated call to a future version or delete the dead API entirely
  2. Never call the private _py_warnings._deprecated from application code; use warnings.warn or warnings.deprecated instead
  3. Re-sync your checkout so Lib/ matches the running interpreter version

Example fix

// before
_deprecated('ssl.wrap_socket', remove=(3, 12))  # RuntimeError on 3.13

# after
_deprecated('ssl.wrap_socket', remove=(3, 14))  # or remove the API outright
Defensive patterns

Strategy: validation

Validate before calling

# CPython maintainers only
import sys
assert sys.version_info[:2] < remove or sys.version_info[3] == 'alpha', \
    f'removal version {remove} already reached'

Prevention

When it happens

Trigger: Only triggerable inside CPython's own Lib/ code or by importing and calling _py_warnings._deprecated directly with a stale remove tuple; e.g. _deprecated('old_api', remove=(3, 12)) on Python 3.13+. Also fires for stdlib modules whose removal bump was merged but the version check still points at an older release.

Common situations: Vendoring or forking CPython Lib code and carrying old _deprecated calls forward; checking out mismatched Lib/ and interpreter versions in a build; patching _version to a tuple that trips the comparison in tests.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/1fc44025ea0b589d. Report an issue: GitHub.