python/cpython · warning

detach_thread: failed detaching thread\n

Error message

detach_thread: failed detaching thread\n

What it means

Diagnostic printed to stderr by the _thread module's ThreadHandle implementation when the underlying OS call to detach a joinable thread fails (non-zero return) during interpreter/thread teardown. It indicates the OS refused to detach — typically because the thread is not in a detachable state — but execution continues; it is a warning-level trace, not a raised exception.

Source

Thrown at Modules/_threadmodule.c:261

    return self;
}

static void
ThreadHandle_incref(ThreadHandle *self)
{
    _Py_atomic_add_ssize(&self->refcount, 1);
}

static int
detach_thread(ThreadHandle *self)
{
    if (!self->has_os_handle) {
        return 0;
    }
    // This is typically short so no need to release the GIL
    if (PyThread_detach_thread(self->os_handle)) {
        fprintf(stderr, "detach_thread: failed detaching thread\n");
        return -1;
    }
    return 0;
}

// NB: This may be called after the PyThreadState in `thread_run` has been
// deleted; it cannot call anything that relies on a valid PyThreadState
// existing.
static void
ThreadHandle_decref(ThreadHandle *self)
{
    if (_Py_atomic_add_ssize(&self->refcount, -1) > 1) {
        return;
    }

    // Remove ourself from the global list of handles
    HEAD_LOCK(&_PyRuntime);
    if (self->node.next != NULL) {

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Ensure threads are either joined (thread.join()) or fully detached consistently before interpreter shutdown
  2. Avoid mixing raw pthread_create/detach from extensions with Python _thread handles for the same thread
  3. Upgrade CPython — thread teardown handling in this path has seen fixes across releases
  4. If it only appears at exit with daemon threads, convert critical threads to non-daemon and join them
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: ThreadHandle cleanup at interpreter shutdown or Thread object deallocation calling PyThread_detach_thread() on pthreads whose state is no longer joinable-detachable (already exited and reaped, or detached elsewhere); races between thread exit and handle finalization.

Common situations: Heavy multithreaded programs embedding CPython exiting while daemon threads are being torn down; C extensions creating raw pthreads that interact with Python thread handles; observed on platforms with stricter pthread lifecycle enforcement. No Python-level exception is raised.

Related errors


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