{"record":{"id":"2cc58ccc0f60f1fb","repo":"paperclipai/paperclip","slug":"acpx-agent-runtime-executable-must-be-a-bounded","errorCode":null,"errorMessage":"ACPX ${agent} runtime executable must be a bounded executable file","messagePattern":"ACPX (.+?) runtime executable must be a bounded executable file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts","lineNumber":1051,"sourceCode":"    handle = await open(\n      executablePath,\n      verifiedExecutableOpenFlags(process.platform, constants.O_NOFOLLOW),\n    );\n  } catch {\n    throw new Error(\n      `ACPX ${agent} runtime executable could not be opened as a no-follow regular file`,\n    );\n  }\n\n  try {\n    const before = await handle.stat({ bigint: true });\n    if (\n      !before.isFile() ||\n      before.size < 1n ||\n      before.size > BigInt(MAX_ACPX_RUNTIME_EXECUTABLE_BYTES) ||\n      (before.mode & 0o111n) === 0n\n    ) {\n      throw new Error(\n        `ACPX ${agent} runtime executable must be a bounded executable file`,\n      );\n    }\n    const hash = createHash(\"sha256\");\n    const buffer = Buffer.alloc(1024 * 1024);\n    let position = 0;\n    try {\n      while (position < Number(before.size)) {\n        const { bytesRead } = await handle.read(\n          buffer,\n          0,\n          Math.min(buffer.length, Number(before.size) - position),\n          position,\n        );\n        if (bytesRead === 0) break;\n        hash.update(buffer.subarray(0, bytesRead));\n        position += bytesRead;\n      }","sourceCodeStart":1033,"sourceCodeEnd":1069,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts#L1033-L1069","documentation":"Once the file is open, the runtime fstat's it and requires the executable to be a regular file of nonzero size, no larger than MAX_ACPX_RUNTIME_EXECUTABLE_BYTES, with at least one execute bit set (mode & 0o111). This bounds the hashing work and ensures the file is actually an executable. Any violation of size or mode throws this error.","triggerScenarios":"fstat via the opened handle returns size 0 (truncated/partial download), size above MAX_ACPX_RUNTIME_EXECUTABLE_BYTES, the opened inode is not a regular file (rare after the open checks), or permission bits have no x bit set (chmod a-x, copied with permissions stripped).","commonSituations":"Interrupted download/copy left a zero-byte or partial binary; a packaging step stripped the executable bit (git checkout on a filesystem without exec bits, or Windows->Unix copy); someone replaced the binary with a huge blob (e.g. a tarball) at the expected path; a copied binary lacks mode bits.","solutions":["Reinstall or re-download the ACPX runtime so the binary is complete (size > 0 and within the size bound)","Restore the execute bit: `chmod +x <path-to-acpx-binary>`","Verify the file at the configured path is the actual binary, not an archive or payload placed there by mistake","Check the binary size against MAX_ACPX_RUNTIME_EXECUTABLE_BYTES if you ship a custom build","Copy the binary with permission preservation (`cp -p` / `install -m 0755`) instead of a plain copy"],"exampleFix":"// before\n-rw-r--r-- acpx  # 0 bytes after interrupted download\n// after\nrm acpx && installer reinstall acpx\nchmod +x /opt/acpx/bin/acpx   # -rwxr-xr-x","handlingStrategy":"validation","validationCode":"import { statSync } from 'node:fs';\nfunction looksLikeExecutable(p: string, maxBytes: number): boolean {\n  try {\n    const st = statSync(p);\n    return st.isFile() && st.size > 0 && st.size <= maxBytes && (st.mode & 0o111) !== 0;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startAcppRuntime();\n} catch (e) {\n  if (String(e?.message).includes('must be a bounded executable file')) {\n    // reinstall or chmod +x the binary, then retry\n    await repairAcpxInstallation();\n    await startAcppRuntime();\n  } else {\n    throw e;\n  }\n}","preventionTips":["Run the official installer rather than hand-copying binaries","Use `install -m 0755` or `cp -p` so execute bits survive copies","Validate download completeness (expected size/checksum) before placing the binary","Ensure the install filesystem supports exec bits (avoid mounts without permission metadata)"],"tags":["filesystem","security","acpx","permissions"],"backgroundTag":"invalid-argument-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}