oracle/graal · critical

Failed to open %s: %s

Error message

Failed to open %s: %s

What it means

Printed by mokapot.c when os_dl_open (dlopen/LoadLibrary) fails to load libjavavm from a derived path, and NULL is returned, aborting JVM creation. mokapot computes the libjavavm location by replacing its own library name inside its loaded path with 'libjavavm.so'; if that file is missing, unreadable, or has unresolved dependencies, the dynamic loader error is printed alongside the path.

Source

Thrown at espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c:1876

        // .../lib/<arch>/truffle/libjvm.so
        //        ^
        if (pos - mokapot_path < 3 || strncmp(pos - 3, EXPECT_LIB, 3) != 0) {
            return NULL;
        }
    }
    unsigned long prefix_len = pos - 3 - mokapot_path;
    size_t lib_name_len = strlen(lib_path);
    if (prefix_len + lib_name_len + 1 > MAX_PATH) {
        return NULL;
    }
    char espresso_path[MAX_PATH];
    strncpy(espresso_path, mokapot_path, prefix_len);
    strncpy(espresso_path + prefix_len, lib_path, MAX_PATH - prefix_len);
    espresso_path[prefix_len + lib_name_len] = '\0';

    OS_DL_HANDLE libjavavm = os_dl_open(espresso_path);
    if (libjavavm == NULL) {
        fprintf(stderr, "Failed to open %s: %s" OS_NEWLINE_STR, espresso_path, os_dl_error());
        return NULL;
    }

#define BIND_LIBJAVAVM_SVM_API(X) \
    graal_ ## X ## _fn_t graal_ ## X = os_dl_sym(libjavavm, "graal_" #X); \
    if (graal_ ## X == NULL) { \
        graal_ ## X = os_dl_sym(libjavavm, "truffle_isolate_" #X); \
        if (graal_ ## X == NULL) { \
            fprintf(stderr, "%s does not contain the expected libjavavm interface: missing " #X OS_NEWLINE_STR, espresso_path); \
            return NULL; \
        } \
    }

#define BIND_LIBJAVAVM(X) \
    X ## _fn_t X = os_dl_sym(libjavavm, #X); \
    if (X == NULL) { \
        fprintf(stderr, "%s does not contain the expected libjavavm interface: missing " #X OS_NEWLINE_STR, espresso_path); \
        return NULL; \

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Verify the printed espresso_path exists and is readable: ls -l <espresso_path>
  2. Check unresolved dependencies: ldd <espresso_path> (or dumpbin on Windows) and install/ship the missing libs
  3. Keep libjavavm.so in the same directory layout relative to libmokapot.so as in the original GraalVM distribution
  4. Rebuild/redeploy with matching GraalVM/Espresso component versions

Example fix

# diagnose
ldd /path/to/libjavavm.so   # look for 'not found' entries
# fix by shipping the missing dependency next to it
export LD_LIBRARY_PATH=/app/libs:$LD_LIBRARY_PATH
Defensive patterns

Strategy: fallback

Validate before calling

# before embedding mokapot, verify libjavavm is resolvable
ls -l "$(dirname libmokapot.so)/libjavavm.so" || echo "missing libjavavm next to mokapot"
ldd "$(dirname libmokapot.so)/libjavavm.so" | grep 'not found' && echo "unresolved deps"

Prevention

When it happens

Trigger: Deploying libmokapot.so without libjavavm.so next to (or in the relative position matching) it; partial native-image extractions; ABI/library-version mismatch (libjavavm built against a different libgraal); missing transitive shared libraries reported by os_dl_error().

Common situations: Bundling only some .so files into a Docker image; LD_LIBRARY_PATH/finalName tricks that relocate libjavavm; upgrading GraalVM while shipping stale native libraries from the previous version.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/2f2f87a4cfeb6372. Report an issue: GitHub.