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
- Verify the printed espresso_path exists and is readable: ls -l <espresso_path>
- Check unresolved dependencies: ldd <espresso_path> (or dumpbin on Windows) and install/ship the missing libs
- Keep libjavavm.so in the same directory layout relative to libmokapot.so as in the original GraalVM distribution
- 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
- Ship libjavavm.so with the same relative layout as the GraalVM distribution
- Run ldd on libjavavm.so as part of deployment checks
- Keep libmokapot, libjavavm, and the GraalVM build on matched versions
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
- Calling unimplemented mokapot %s
- Memory access is outside the boundaries of the allocated mem
- [eden #%ld] FATAL ERROR
- Cannot bind label to negative position %d
- Out of scratch registers: %s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/2f2f87a4cfeb6372.
Report an issue: GitHub.