{"record":{"id":"749375b949ab132c","repo":"openjdk/jdk","slug":"unexpected-error-d-returned-by-addtosystemclass","errorCode":null,"errorMessage":"Unexpected error (%d) returned by AddToSystemClassLoaderSearch\\n","messagePattern":"Unexpected error \\((.+?)\\) returned by AddToSystemClassLoaderSearch\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/java.instrument/share/native/libinstrument/InvocationAdapter.c","lineNumber":804,"sourceCode":" */\nstatic int\nappendClassPath( JPLISAgent* agent,\n                 const char* jarfile ) {\n    jvmtiEnv* jvmtienv = jvmti(agent);\n    jvmtiError jvmtierr;\n\n    jvmtierr = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, jarfile);\n    check_phase_ret_1(jvmtierr);\n\n    switch (jvmtierr) {\n        case JVMTI_ERROR_NONE :\n            return 0;\n        case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED :\n            fprintf(stderr, \"System class loader does not define \"\n                \"the appendToClassPathForInstrumentation method\\n\");\n            break;\n        default:\n            fprintf(stderr, \"Unexpected error (%d) returned by \"\n                \"AddToSystemClassLoaderSearch\\n\", jvmtierr);\n            break;\n    }\n    return -1;\n}\n\n\n/*\n * res = func, free'ing the previous value of 'res' if function\n * returns a new result.\n */\n#define TRANSFORM(res,func) {    \\\n    char* tmp = func;            \\\n    if (tmp != res) {            \\\n        free(res);               \\\n        res = tmp;               \\\n    }                            \\\n    jplis_assert((void*)res != (void*)NULL);     \\","sourceCodeStart":786,"sourceCodeEnd":822,"githubUrl":"https://github.com/openjdk/jdk/blob/88dfb74bbeefcf2b0aa11835183bcd949998fc8f/src/java.instrument/share/native/libinstrument/InvocationAdapter.c#L786-L822","documentation":"Diagnostic printed by appendClassPath: JVMTI AddToSystemClassLoaderSearch returned an error other than NONE or CLASS_LOADER_UNSUPPORTED (the numeric code is printed). Causes are JVM-internal conditions such as an invalid/no-longer-existent jar path, wrong phase, or out-of-memory inside the JVMTI call.","triggerScenarios":"Agent jar path that vanishes between resolution and the JVMTI call (deleted tmp file); attaching past the live phase where the call is disallowed (check_phase already filters some); JVMTI_ERROR_ILLEGAL_ARGUMENT from a malformed path; native OOM.","commonSituations":"Attaching agents from short-lived tmp files that get cleaned up; attaching to a JVM that is shutting down; exotic path encodings.","solutions":["Note the numeric code and match it against jvmtiError values (e.g. 20=ILLEGAL_ARGUMENT, 30=WRONG_PHASE, 101=NULL_POINTER)","Ensure the agent jar path is stable and absolute for the lifetime of the attach","Attach while the JVM is in the live phase, not during shutdown","Retry the attach once transient conditions (shutdown, heavy GC) clear"],"exampleFix":"# before\nvm.loadAgent(\"/tmp/tmp1234/agent.jar\"); // tmp cleaner races\n# after\ncp agent.jar /opt/agents/agent.jar\nvm.loadAgent(\"/opt/agents/agent.jar\");","handlingStrategy":"retry","validationCode":"// confirm the jar still exists right before attach\nif (!Files.isReadable(Path.of(agentPath))) throw new IllegalStateException(\"agent jar vanished: \" + agentPath);","typeGuard":null,"tryCatchPattern":"for (int i = 0; i < 2; i++) {\n    try { vm.loadAgent(agentPath); break; }\n    catch (AgentInitializationException e) {\n        if (i == 1 || e.returnValue() != 104) throw e; // retry only transient append failures\n    }\n}","preventionTips":["Use durable, absolute paths for agent jars","Attach while the JVM is healthy in live phase, not during startup/shutdown storms"],"tags":["java-instrument","jvmti","diagnostics","classpath","attach-api"],"backgroundTag":null,"analyzedSha":"88dfb74bbeefcf2b0aa11835183bcd949998fc8f","analyzedAt":"2026-08-14T11:45:09.665Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}