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

  1. Install glibc (libc6 / glibc package) so libc.so.6 exists and ldconfig cache is populated.
  2. On musl systems, install gcompat or a libc.musl shim and add a libc.so symlink pointing at it.
  3. Verify manually: `bun -e 'require("bun:ffi").dlopen("libc.so.6",{})'` and fix whatever it reports.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f420f85511a9cf2f. Report an issue: GitHub.