openjdk/jdk · error

Unexpected error (%d) returned by AddToSystemClassLoaderSear

Error message

Unexpected error (%d) returned by AddToSystemClassLoaderSearch\n

What it means

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.

Source

Thrown at src/java.instrument/share/native/libinstrument/InvocationAdapter.c:804

 */
static int
appendClassPath( JPLISAgent* agent,
                 const char* jarfile ) {
    jvmtiEnv* jvmtienv = jvmti(agent);
    jvmtiError jvmtierr;

    jvmtierr = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, jarfile);
    check_phase_ret_1(jvmtierr);

    switch (jvmtierr) {
        case JVMTI_ERROR_NONE :
            return 0;
        case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED :
            fprintf(stderr, "System class loader does not define "
                "the appendToClassPathForInstrumentation method\n");
            break;
        default:
            fprintf(stderr, "Unexpected error (%d) returned by "
                "AddToSystemClassLoaderSearch\n", jvmtierr);
            break;
    }
    return -1;
}


/*
 * res = func, free'ing the previous value of 'res' if function
 * returns a new result.
 */
#define TRANSFORM(res,func) {    \
    char* tmp = func;            \
    if (tmp != res) {            \
        free(res);               \
        res = tmp;               \
    }                            \
    jplis_assert((void*)res != (void*)NULL);     \

View on GitHub (pinned to 88dfb74bbe)

Solutions

  1. Note the numeric code and match it against jvmtiError values (e.g. 20=ILLEGAL_ARGUMENT, 30=WRONG_PHASE, 101=NULL_POINTER)
  2. Ensure the agent jar path is stable and absolute for the lifetime of the attach
  3. Attach while the JVM is in the live phase, not during shutdown
  4. Retry the attach once transient conditions (shutdown, heavy GC) clear

Example fix

# before
vm.loadAgent("/tmp/tmp1234/agent.jar"); // tmp cleaner races
# after
cp agent.jar /opt/agents/agent.jar
vm.loadAgent("/opt/agents/agent.jar");
Defensive patterns

Strategy: retry

Validate before calling

// confirm the jar still exists right before attach
if (!Files.isReadable(Path.of(agentPath))) throw new IllegalStateException("agent jar vanished: " + agentPath);

Try / catch

for (int i = 0; i < 2; i++) {
    try { vm.loadAgent(agentPath); break; }
    catch (AgentInitializationException e) {
        if (i == 1 || e.returnValue() != 104) throw e; // retry only transient append failures
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Attaching agents from short-lived tmp files that get cleaned up; attaching to a JVM that is shutting down; exotic path encodings.

Related errors


AI-assisted analysis of openjdk/jdk@88dfb74bbe (2026-08-14). Data as JSON: /api/errors/749375b949ab132c. Report an issue: GitHub.