{"record":{"id":"f139cde1bfa13c6b","repo":"apache/hadoop","slug":"hdfsthreaddestructor-unable-to-detach-thread-s-f","errorCode":null,"errorMessage":"hdfsThreadDestructor: Unable to detach thread %s from the JVM. Error code: %d\n","messagePattern":"hdfsThreadDestructor: Unable to detach thread (.+?) from the JVM\\. Error code: (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread_local_storage.c","lineNumber":78,"sourceCode":"      fprintf(stderr, \"hdfsThreadDestructor: GetJavaVM failed with error %d\\n\",\n        ret);\n      jthr = (*env)->ExceptionOccurred(env);\n      if (jthr) {\n        (*env)->ExceptionDescribe(env);\n        (*env)->ExceptionClear(env);\n      }\n    } else {\n      ret = (*vm)->DetachCurrentThread(vm);\n\n      if (ret != JNI_OK) {\n        jthr = (*env)->ExceptionOccurred(env);\n        if (jthr) {\n          (*env)->ExceptionDescribe(env);\n          (*env)->ExceptionClear(env);\n        }\n        get_current_thread_id(env, thr_name, MAXTHRID);\n\n        fprintf(stderr, \"hdfsThreadDestructor: Unable to detach thread %s \"\n            \"from the JVM. Error code: %d\\n\", thr_name, ret);\n      }\n    }\n  }\n\n  /* Free exception strings */\n  if (state->lastExceptionStackTrace) free(state->lastExceptionStackTrace);\n  if (state->lastExceptionRootCause) free(state->lastExceptionRootCause);\n\n  /* Free the state itself */\n  free(state);\n}\n\nstatic void get_current_thread_id(JNIEnv* env, char* id, int max) {\n  jvalue jVal;\n  jobject thr = NULL;\n  jstring thr_name = NULL;\n  jlong thr_id = 0;","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread_local_storage.c#L60-L96","documentation":"The POSIX TLS destructor called DetachCurrentThread and the JVM returned something other than JNI_OK — commonly JNI_EDETACHED when the thread was not (or no longer) attached. The printed thread name comes from get_current_thread_id via the JVM. The destructor still frees the state afterwards, so this is a teardown-time warning rather than a crash.","triggerScenarios":"Thread exit after another component already detached it from the JVM; detach attempted while DestroyJavaVM is tearing the runtime down and the JVM refuses.","commonSituations":"Multiple native libraries managing attachment in one process; shutdown ordering races between thread exits and JVM destruction.","solutions":["Treat as informational when it appears during process shutdown","If reproducible mid-run, audit other JNI libraries in-process for double detach","Make threads finish all HDFS work before hdfsDisconnect and teardown paths begin"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid multiple native libraries double-detaching the same thread from the JVM","Complete HDFS operations before initiating JVM teardown","Treat mid-run occurrences as a signal of conflicting JNI management; shutdown-only occurrences as noise"],"tags":["libhdfs","jni","detachcurrentthread","thread-exit","tls-destructor"],"backgroundTag":"jni-thread-detach-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}