apache/hadoop · error

Call to AttachCurrentThread failed with error: %d

Error message

Call to AttachCurrentThread failed with error: %d

What it means

A thread calling into libhdfs found an already-created JVM (JNI_GetCreatedJavaVMs returned one, so this is the second or later thread) and AttachCurrentThread failed with a non-zero JNI code (typically JNI_EVERSION or native-resource failure). getGlobalJNIEnv returns NULL, so this thread's HDFS call fails while other, already-attached threads keep working.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/jni_helper.c:763

                    "with error: %d\n", rv);
            return NULL;
        }

        // We use findClassAndInvokeMethod here because the jclasses in
        // jclasses.h have not loaded yet
        jthr = findClassAndInvokeMethod(env, NULL, STATIC, NULL, HADOOP_FS,
                "loadFileSystems", "()V");
        if (jthr) {
            printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
                    "FileSystem: loadFileSystems failed");
            return NULL;
        }
    } else {
        //Attach this thread to the VM
        vm = vmBuf[0];
        rv = (*vm)->AttachCurrentThread(vm, (void*)&env, 0);
        if (rv != 0) {
            fprintf(stderr, "Call to AttachCurrentThread "
                    "failed with error: %d\n", rv);
            return NULL;
        }
    }

    return env;
}

/**
 * getJNIEnv: A helper function to get the JNIEnv* for the given thread.
 * If no JVM exists, then one will be created. JVM command line arguments
 * are obtained from the LIBHDFS_OPTS environment variable.
 *
 * Implementation note: we rely on POSIX thread-local storage (tls).
 * This allows us to associate a destructor function with each thread, that
 * will detach the thread from the Java VM when the thread terminates.  If we
 * failt to do this, it will cause a memory leak.
 *

View on GitHub (pinned to 2add963021)

Solutions

  1. Warm up each worker thread at startup with a cheap call (hdfsExists on "/") so attachment happens before real work and fails visibly
  2. For code -3 (JNI_EVERSION), align the runtime libjvm with the JVM libhdfs was built against
  3. For other codes, reduce concurrent thread count or raise memory limits so the JVM can allocate thread structures
  4. Make sure no thread issues HDFS calls while the process is tearing the JVM down

Example fix

// before: first libhdfs touch deep inside worker
void* worker(void *arg) {
    hdfsRead(fs, file, buf, n);  /* attach fails mid-job */
}

// after: force attach at thread start, fail fast
void* worker(void *arg) {
    if (!fs_attached_ok()) return NULL;  /* calls any hdfs API to trigger getJNIEnv */
    hdfsRead(fs, file, buf, n);
}
Defensive patterns

Strategy: fallback

Validate before calling

/* Warm up each worker: force attach at thread start, not mid-job */
static void warm_thread(hdfsFS fs) {
    hdfsExists(fs, "/"); /* any call routes through getJNIEnv */
}

Try / catch

if (someHdfsCall(fs) == -1 && errno == EINTERNAL) {
    /* attach failed for this thread; route work to an attached worker */
    enqueue_to_io_thread(op); /* fallback: single dedicated I/O thread */
}

Prevention

When it happens

Trigger: Multi-threaded programs where a worker's first libhdfs call happens after another thread created the VM and the attach fails: JNI version negotiation problems after a JVM change, JVM unable to allocate per-thread native structures under memory pressure, or calls racing JVM destruction at shutdown.

Common situations: Thread pools creating threads late under heavy load; applications embedding libhdfs alongside another JVM owner; shutdown paths where a lingering thread calls an HDFS API while DestroyJavaVM is running.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/7dcb5da0ad9e747f. Report an issue: GitHub.