can1357/oh-my-pi · critical
failed to load libc for Linux child supervision
Error message
failed to load libc for Linux child supervision
What it means
When supervising a child process tree on Linux, ptree spawns a small Bun worker script that dlopens libc via bun:ffi to call prctl(PR_SET_CHILD_SUBREAPER). It tries the candidate sonames (libc.so.6, then libc.so) and throws this error only if every candidate fails to load. It means the FFI bridge to libc could not be established, so child reaping cannot work.
Source
Thrown at packages/utils/src/ptree.ts:47
import { dlopen, FFIType } from "bun:ffi";
let libc;
for (const soname of ${JSON.stringify(libcCandidates)}) {
try {
libc = dlopen(soname, {
prctl: {
args: [FFIType.i32, FFIType.u64, FFIType.u64, FFIType.u64, FFIType.u64],
returns: FFIType.i32,
},
waitpid: {
args: [FFIType.i32, FFIType.ptr, FFIType.i32],
returns: FFIType.i32,
},
});
break;
} catch {}
}
if (!libc) throw new Error("failed to load libc for Linux child supervision");
if (libc.symbols.prctl(36, 1, 0, 0, 0) !== 0) {
throw new Error("failed to become a Linux child subreaper");
}
const commandJson = Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};
if (!commandJson) throw new Error("missing supervised command");
const callerBunBeBun = Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};
delete Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};
delete Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};
if (callerBunBeBun === undefined) delete Bun.env.BUN_BE_BUN;
else Bun.env.BUN_BE_BUN = callerBunBeBun;
const command = JSON.parse(commandJson);
const child = Bun.spawn(command, {
stdin: "inherit",
stdout: "pipe",
stderr: "pipe",
windowsHide: true,View on GitHub (pinned to 9690622007)
Solutions
- Install glibc (libc6 / glibc package) so libc.so.6 exists and ldconfig cache is populated.
- On musl systems, install gcompat or a libc.musl shim and add a libc.so symlink pointing at it.
- Verify manually: `bun -e 'require("bun:ffi").dlopen("libc.so.6",{})'` and fix whatever it reports.
- Run on a glibc-based base image (e.g. debian:bookworm-slim instead of alpine).
Example fix
// Dockerfile before (Alpine, no glibc) FROM node:alpine // after FROM node:bookworm # or: apk add gcompat
Defensive patterns
Strategy: fallback
Validate before calling
import { dlopen } from 'bun:ffi';
for (const soname of ['libc.so.6', 'libc.so']) {
try { dlopen(soname, {}); break; } catch {}
throw new Error(`libc not loadable: ${soname}`);
} Try / catch
try {
await runSupervised(cmd);
} catch (err) {
if (String(err.message).includes('failed to load libc')) {
// fall back to direct spawn without subreaper supervision
await Bun.spawn(cmd).exited;
} else throw err;
} Prevention
- Use glibc-based base images for anything that supervises child processes.
- Smoke-test dlopen('libc.so.6') in container startup checks.
- On musl, install gcompat and verify the libc.so symlink exists.
When it happens
Trigger: Running a Linux supervised spawn (Bun.spawn with subreaper supervision) on a system where neither 'libc.so.6' nor 'libc.so' can be dlopen'd by Bun — e.g. musl-based distros (Alpine) without glibc compat, minimal containers missing the loader cache, or a stripped runtime without bun:ffi support.
Common situations: Alpine/musl Docker images, distroless containers, NixOS with unusual library paths, or cross-distro binaries where glibc sonames are absent.
Related errors
- missing supervised command
- native task `{tag}` panicked: {message}
- path contains NUL
- ${argv[0]} exited with code ${exitCode}: ${stderr.trim().sli
- ${argv[0]} printed no URL on stdout
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f420f85511a9cf2f.
Report an issue: GitHub.