SeleniumHQ/selenium · error
Failed to dlopen %s
Error message
Failed to dlopen %s
What it means
stderr diagnostic from get_xlib_handle() emitted when dlopen(library, RTLD_LAZY) returns NULL after a candidate libX11 path was successfully located by arch or env. Unlike error 501 (library not found), here the file exists and has the right ELF machine type, but the dynamic loader refused to map it. The immediately following line prints dlerror() with the precise reason. The function still returns NULL, so the focus-prevention shim is disabled exactly as in the not-found case, but the fix is different: this is a shared-library dependency or permission problem, not a missing-library problem.
Source
Thrown at cpp/linux-specific/x_ignore_nofocus.c:640
if (suitable_xlib_index >= 0) {
snprintf(library, MAX_LIBRARY_PATH, "%s", possible_locations[suitable_xlib_index]);
found_library = TRUE;
} else {
found_library = find_xlib_by_env(library, required_lib_arch);
}
if (found_library == FALSE) {
const char* desired_arch = (required_lib_arch == EM_386 ? "32-bit" : "64-bit");
fprintf(stderr, "None of the following is a %s version of Xlib:", desired_arch);
int i;
for (i = 0; i < locations_len; i++) {
fprintf(stderr, " %s\n", possible_locations[i]);
}
return NULL;
}
ret_handle = dlopen(library, RTLD_LAZY);
if (ret_handle == NULL) {
fprintf(stderr, "Failed to dlopen %s\n", library);
fprintf(stderr, "dlerror says: %s\n", dlerror());
}
return ret_handle;
}
void print_event_to_log(Display* dpy, XEvent* ev)
{
#ifdef DEBUG_PRINTOUTS
if ((ev->type != PropertyNotify) && (ev->type != ConfigureNotify)) {
print_event(g_out_stream, ev, dpy);
}
#endif
}
// This global variable is intentionally declared here - as I wish the rest
// of the functions will act on it as a parameter.
FocusKeepStatus g_focus_status;View on GitHub (pinned to aa36b38e69)
Solutions
- Read the next stderr line ('dlerror says: ...') for the exact loader error; it usually names the missing symbol or undefined library.
- Run `ldd <path-from-the-message>` on the dlopened libX11.so.6 and install every dependency it reports as 'not found' (commonly `apt-get install -y libxcb1 libxau6 libxdmcp6`).
- If on Alpine/musl, switch to a glibc-based image (or install gcompat) because the native helper is built against glibc and dlopen of a musl libX11 will fail at symbol resolution.
- For SELinux denials, check `ausearch -m avc -ts recent` / `dmesg | grep -i selinux` and adjust the context or set the host to permissive for diagnosis; for a corrupt .so, `apt-get install --reinstall libx11-6`.
Example fix
# before (libX11 present but dlopen fails: missing libxcb) # stderr: # Failed to dlopen /usr/lib/x86_64-linux-gnu/libX11.so.6 # dlerror says: libxcb.so.1: cannot open shared object file # after apt-get update && apt-get install -y libxcb1 libxau6 java -jar selenium-server.jar # dlopen succeeds, get_xlib_handle returns non-NULL
Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env bash
# Validate that the located libX11 can actually be loaded before launching Selenium.
LIB="$(ldconfig -p | awk '/libX11\.so\.6$/ {print $NF; exit}')"
[ -n "$LIB" ] || { echo 'libX11.so.6 not in ldconfig cache'; exit 1; }
echo "Checking $LIB"
ldd "$LIB" | grep -i 'not found' && {
echo 'FAIL: libX11 has unresolved dependencies; install them (libxcb1, libxau6, ...)'
exit 1
}
# Probe an actual dlopen the way the helper will
python3 - "$LIB" <<'PY' || { echo 'FAIL: dlopen rejected libX11'; exit 1; }
import sys, ctypes
ctypes.CDLL(sys.argv[1], mode=ctypes.RTLD_LAZY)
print('OK: dlopen succeeded')
PY Prevention
- Always install libX11's runtime dependencies alongside it (`apt-get install -y libx11-6 libxcb1 libxau6 libxdmcp6`), not just libX11 itself.
- On Alpine/musl, use a glibc base image or gcompat; the native helper is glibc-built and dlopen of musl libs fails.
- Run `ldd` on libX11.so.6 in your image build to catch missing transitive deps before runtime.
- Keep SELinux/AppArmor policy permissive for the JVM loading native helpers, or label the .so correctly; check `dmesg`/`ausearch` when dlopen fails silently.
When it happens
Trigger: dlopen() fails on a found libX11.so.6 inside get_xlib_handle() — most often because a transitive dependency (libxcb.so.1, libXau.so.6, libXdmcp.so.0, libdl.so.2, or a glibc symbol version) is missing or the wrong ABI; also when SELinux/AppArmor denies the load, the .so is corrupt or truncated, or there is a glibc-vs-musl mismatch (e.g. glibc-built helper loading a musl-system libX11).
Common situations: Slimmed Alpine/musl-based images (the helper is built against glibc); containers that installed libX11 but not libxcb1/libXau6; partial apt upgrades leaving libX11 without its runtime deps; SELinux enforcing mode blocking .so load; corrupt package install; multi-arch systems pulling the wrong libxcb alongside the right libX11.
Related errors
- None of the following is a %s version of Xlib:
- %s
- Can't find java on system PATH. JRE is required to run the S
- module {__name__!r} has no attribute {name!r}
- service_args must be a sequence
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/33d396c8cf79070b.
Report an issue: GitHub.