paperclipai/paperclip · error · Error
ACPX runtime executable must be a bounded executable file
Error message
ACPX runtime executable must be a bounded executable file
What it means
When snapshotting the ACPX runtime executable itself, createAcpxPrivateSnapshot requires the file handle's stat to show a regular file with size between 1 byte and MAX_ACPX_RUNTIME_EXECUTABLE_BYTES. Otherwise it throws this error, refusing to bundle an empty, non-regular, or oversized runtime binary into the private snapshot.
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/private-snapshot.ts:189
}
}
for (const root of roots)
for (const pkg of packages) {
const target = join(root, "node_modules", pkg.name);
await mkdir(dirname(target), { recursive: true, mode: 0o700 });
// Include generated directories in cleanup and read-only sealing.
directories.push(join(root, "node_modules"), dirname(target));
await symlink(pkg.root, target).catch(
(error: NodeJS.ErrnoException) => {
if (error.code !== "EEXIST") throw error;
},
);
}
let executablePath: string | null = null;
if (executable) {
const before = await executable.stat({ bigint: true });
if (!before.isFile() || before.size < 1n || before.size > BigInt(MAX_ACPX_RUNTIME_EXECUTABLE_BYTES)) {
throw new Error("ACPX runtime executable must be a bounded executable file");
}
// The bigint bound above makes this conversion exact before allocation.
const executableBytes = Number(before.size);
bytesCopied += executableBytes;
if (bytesCopied > MAX_SNAPSHOT_BYTES) {
throw new Error("ACPX snapshot exceeds its byte bound");
}
const bytes = await readSnapshotBytes(executable, executableBytes);
if (!same(before, await executable.stat({ bigint: true })))
throw new Error("ACPX executable changed during snapshot");
executablePath = join(directory, "runtime");
await writeFile(executablePath, bytes, { flag: "wx", mode: 0o500 });
digests[executablePath] = digest(bytes);
}
const manifest = Buffer.from(
JSON.stringify({ roots, executable: executablePath, digests }),
);
const manifestPath = join(directory, "manifest.json");View on GitHub (pinned to 01ad858492)
Solutions
- Verify the executable path resolves to the real, fully-built runtime binary (check file size is nonzero and plausible)
- Reinstall/rebuild the ACPX runtime if the binary is truncated or empty
- If you ship a legitimately larger runtime, adjust MAX_ACPX_RUNTIME_EXECUTABLE_BYTES in the runner configuration consciously
- Ensure the path points at a regular file, not a script wrapper that is a symlink chain, fifo, or directory
Example fix
// before: placeholder stub executablePath: './bin/acpx-stub' // 0 bytes // after: real built binary executablePath: './dist/bin/acpx' // regular file within bound
Defensive patterns
Strategy: validation
Validate before calling
const st = await fs.stat(executablePath);
if (!st.isFile() || st.size < 1 || st.size > MAX_ACPX_RUNTIME_EXECUTABLE_BYTES) {
throw new Error(`invalid runtime executable at ${executablePath}: size=${st.size}`);
} Type guard
function isValidRuntimeExecutable(st: { isFile(): boolean; size: number }): boolean {
return st.isFile() && st.size >= 1 && st.size <= MAX_ACPX_RUNTIME_EXECUTABLE_BYTES;
} Try / catch
try {
await createAcpxPrivateSnapshot({ roots, executable });
} catch (e) {
if (e.message.includes('runtime executable must be a bounded executable file')) {
throw new Error(`Rebuild or reconfigure the ACPX runtime at ${executable.path}; it is empty, special, or oversized`);
}
throw e;
} Prevention
- Validate the runtime binary exists, is nonzero, and within the size bound at startup
- Reinstall the runtime after partial downloads or failed builds
- Keep wrapper scripts distinct from the binary; point configuration at the regular-file binary
When it happens
Trigger: createAcpxPrivateSnapshot is called with an `executable` whose stat({bigint:true}) reports isFile() === false, size === 0n, or size > MAX_ACPX_RUNTIME_EXECUTABLE_BYTES — i.e. the resolved ACPX runtime binary is missing content, a special file, or abnormally large.
Common situations: Misconfigured executable path pointing at a wrapper/stub or empty placeholder; a partially downloaded or truncated runtime binary; a custom runtime build that ballooned past the configured byte limit; pointing at a directory or device node by mistake.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- ACPX package snapshot exceeds its file bound
- ACPX module must be a bounded regular file
- ACPX package snapshot exceeds its byte bound
- A trusted viewer build is required for public chat reports
- Private state directory is not a real directory: ${diagnosti
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/daf36c1ee867534c.
Report an issue: GitHub.