python/cpython · warning · RuntimeError

Must run this script from the repo root

Error message

Must run this script from the repo root

What it means

In debug mode, selector- and proactor-based event loops verify that sockets used with the sock_* APIs are non-blocking (gettimeout() == 0), because the whole sock_* design assumes the loop drives readiness. This instance is in BaseSelectorEventLoop.sock_connect (Lib/asyncio/selector_events.py:381 region). A blocking socket would freeze the loop, so debug mode fails fast with ValueError instead.

Source

Thrown at Doc/tools/check-warnings.py:312

        "--fail-if-new-news-nit",
        metavar="threshold",
        type=int,
        nargs="?",
        const=NEWS_NIT_THRESHOLD,
        help="Fail if new NEWS nit found before threshold line number",
    )

    args = parser.parse_args(argv)
    if args.annotate_diff is not None and len(args.annotate_diff) > 2:
        parser.error(
            "--annotate-diff takes between 0 and 2 ref args, not "
            f"{len(args.annotate_diff)} {tuple(args.annotate_diff)}"
        )
    exit_code = 0

    wrong_directory_msg = "Must run this script from the repo root"
    if not Path("Doc").exists() or not Path("Doc").is_dir():
        raise RuntimeError(wrong_directory_msg)

    warnings = (
        Path("Doc/sphinx-warnings.txt")
        .read_text(encoding="UTF-8")
        .splitlines()
    )

    cwd = str(Path.cwd()) + os.path.sep
    files_with_nits = {
        warning.removeprefix(cwd).split(":")[0]
        for warning in warnings
        if "Doc/" in warning
    }

    with Path("Doc/tools/.nitignore").open(encoding="UTF-8") as clean_files:
        files_with_expected_nits = {
            filename.strip()
            for filename in clean_files

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Set the socket non-blocking before use: sock.setblocking(False) (equivalently settimeout(0.0))
  2. Pass the socket through the loop-managed APIs (loop.sock_connect + await) consistently instead of mixing blocking and async calls on one fd
  3. Disable debug mode only as a last resort and never as the real fix — the check indicates a genuine freeze hazard

Example fix

# before
sock = socket.socket()
await loop.sock_connect(sock, addr)  # debug mode: ValueError
# after
sock = socket.socket()
sock.setblocking(False)
await loop.sock_connect(sock, addr)
Defensive patterns

Strategy: validation

Validate before calling

def loop_ready_socket(sock):
    if sock.gettimeout() != 0:
        sock.setblocking(False)
    return sock

async def connect(loop, sock, addr):
    return await loop.sock_connect(loop_ready_socket(sock), addr)

Try / catch

try:
    await loop.sock_connect(sock, addr)
except ValueError as e:
    if 'non-blocking' in str(e):
        sock.setblocking(False)
        return await loop.sock_connect(sock, addr)
    raise

Prevention

When it happens

Trigger: Enabling asyncio debug mode (PYTHONASYNCIODEBUG=1, asyncio.run(debug=True), or loop.set_debug(True)) and calling sock_connect()/sock_* with a socket whose timeout is not 0 — e.g. a freshly created socket (default timeout None) or one set with settimeout(5). The proactor loop's sock_connect applies the same check.

Common situations: Code that worked in normal mode suddenly raising after debug mode is turned on for diagnosis; sockets created by third-party libraries (requests, socket.create_connection) that have blocking timeouts; tests running with faulthandler/debug fixtures that enable loop debug globally.

Related errors


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