oracle/graal · critical
[eden #%ld] FATAL ERROR
Error message
[eden #%ld] FATAL ERROR
What it means
In eden.c (the native library that gives each Espresso context its own linker namespace via dlmopen), FATAL is a macro that prints '[eden #<ns>] FATAL ERROR <msg>' to stderr and calls exit(-1), killing the whole process. It is used when an unrecoverable native invariant fails (e.g. glibc symbol resolution or namespace setup).
Source
Thrown at espresso/src/com.oracle.truffle.espresso.eden/src/eden.c:47
#include <unistd.h>
#include <dlfcn.h>
#include <gnu/libc-version.h>
#define UNINITIALIZED ((void*) ~0)
extern void *__libc_dlsym(void *handle, const char *symbol);
extern void *__libc_dlopen_mode(const char *filename, int flags);
extern const unsigned short int ** __ctype_b_loc (void);
// Linking namespace where this library is loaded.
static Lmid_t namespace_id = 0;
// Debug flags, can be set with EDEN_DEBUG=true|1
static int eden_debug = 0;
#define LOG(fmt, ...) do { if (eden_debug) fprintf(stderr, "[eden #%ld] " fmt, namespace_id, ##__VA_ARGS__); } while (0)
#define FATAL(fmt, ...) do { fprintf(stderr, "[eden #%ld] FATAL ERROR " fmt, namespace_id, ##__VA_ARGS__); exit(-1); } while (0)
static int glibc_major = 0;
static int glibc_minor = 0;
static void *real_dlopen(const char *filename, int flags) {
LOG("real_dlopen(%s, %d)\n", filename, flags);
static void *(*the_real_dlopen)(const char *, int) = NULL;
if (the_real_dlopen == NULL) {
LOG("dlsym(RTLD_NEXT, dlopen)\n");
the_real_dlopen = dlsym(RTLD_NEXT, "dlopen");
LOG("dlsym(RTLD_NEXT, dlopen) => %p\n", the_real_dlopen);
}
void *result = the_real_dlopen(filename, flags);
LOG("real_dlopen(%s, %d) => %p\n", filename, flags, result);
return result;
}
static void *get_libc() {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Set EDEN_DEBUG=true (or 1) to get the LOG trace before the fatal and identify which lookup failed.
- Run on a standard glibc distribution (not musl/Alpine) with a supported glibc version.
- Raise limits on namespaces/threads if many contexts are used; reduce concurrent contexts loading native libs.
- Report the FATAL message plus glibc version and repro to the GraalVM issue tracker.
Defensive patterns
Strategy: try-catch
Validate before calling
// Eden cannot be caught (exit(-1)); validate the environment instead // run on glibc, check RLIMIT/namespace limits before creating many contexts
Prevention
- Run on standard glibc distros; avoid musl/Alpine for eden-based isolation.
- Set EDEN_DEBUG=true when diagnosing to capture the LOG trace before a FATAL.
- Limit the number of concurrent contexts that load native libraries.
When it happens
Trigger: Eden's FATAL sites: glibc version detection failing, __libc_dlopen_mode/dlsym lookup failures, or dlmopen namespace limits (RLIMIT/NSS module loading) when creating many contexts with isolated native libraries.
Common situations: Running many Espresso contexts each loading native libraries (per-context linker namespaces); restrictive container seccomp/rlimits; unusual glibc versions (musl-based images are unsupported); LD_PRELOAD interposition breaking dlsym(RTLD_NEXT, ...).
Related errors
- Memory access is outside the boundaries of the allocated mem
- Calling unimplemented mokapot %s
- Failed to open %s: %s
- 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/fa46489d440aa401.
Report an issue: GitHub.