can1357/oh-my-pi · critical
failed to become a Linux child subreaper
Error message
failed to become a Linux child subreaper
What it means
The subreaper worker successfully loaded libc and called prctl(36 /* PR_SET_CHILD_SUBREAPER */, 1, 0, 0, 0), but the kernel returned non-zero, so the process could not be registered as a child subreaper. ptree throws rather than supervising without reaping ability, since orphaned grandchildren would be left untracked.
Source
Thrown at packages/utils/src/ptree.ts:50
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,
env: Bun.env,
});
View on GitHub (pinned to 9690622007)
Solutions
- Inspect the seccomp/sandbox profile and allow prctl (syscall 157 on x86_64).
- Run the process outside the restricting sandbox (e.g. without gVisor) to confirm the cause.
- If the platform cannot support subreapers, use a supervision mode that does not require the subreaper worker.
Example fix
// docker run before (default restrictive profile) docker run --security-opt seccomp=hardened.json ... // after docker run --security-opt seccomp=profile-that-allows-prctl.json ...
Defensive patterns
Strategy: try-catch
Try / catch
try {
await runSupervised(cmd);
} catch (err) {
if (String(err.message).includes('child subreaper')) {
logger.warn('subreaper unavailable; sandbox blocks prctl', { err });
// degrade to unsupervised spawn or fail fast with a clear message
} else throw err;
} Prevention
- Audit seccomp/gVisor profiles for prctl (syscall 157) allowlisting before deploying.
- Test supervised spawns inside the actual sandbox/CI environment, not just locally.
- Document sandbox requirements for the deployment target.
When it happens
Trigger: prctl(PR_SET_CHILD_SUBREAPER) returning non-zero — practically only in restricted environments: seccomp/LSM filters blocking prctl (some sandboxes, gVisor, hardened containers), or running under an emulator/OS where prctl(36) is not implemented.
Common situations: Containers with restrictive seccomp profiles (Docker default profiles usually allow prctl, but custom hardened ones may not), gVisor/runsc sandboxes, CI runners with syscall filtering.
Related errors
- path contains NUL
- write() expects string, Blob, ArrayBuffer, or TypedArray dat
- Protocol paths are not supported by ${op}(): ${rawPath}
- Invalid URL encoding in ${scheme}:// path: ${rawPath}
- Absolute paths are not allowed in ${scheme}:// URLs: ${rawPa
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8c1ff2b2de42cbba.
Report an issue: GitHub.