paperclipai/paperclip · error · Error

ACPX module must be a bounded regular file

Error message

ACPX module must be a bounded regular file

What it means

For every non-directory entry, copy() requires it to be a regular file no larger than 16 MiB; otherwise it throws 'ACPX module must be a bounded regular file'. This rejects special files (devices, sockets, FIFOs) and oversized modules, keeping each snapshot module bounded and safely bufferable in memory.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/private-snapshot.ts:120

      const canonical = await realpath(source);
      const mapped = mapPath(canonical);
      // Package-manager links to unqualified packages do not grant import authority.
      if (mapped) await symlink(mapped, target);
      return;
    }
    if (!within(root, await realpath(source)))
      throw new Error("ACPX snapshot escaped its package");
    if (before.isDirectory()) {
      await mkdir(target, { mode: 0o700 });
      directories.push(target);
      for (const entry of await readdir(source))
        await copy(join(source, entry), join(target, entry), root);
      if (!same(before, await lstat(source, { bigint: true })))
        throw new Error("ACPX package directory changed during snapshot");
      return;
    }
    if (!before.isFile() || before.size > 16n * 1024n * 1024n)
      throw new Error("ACPX module must be a bounded regular file");
    bytesCopied += Number(before.size);
    if (bytesCopied > MAX_PACKAGE_SNAPSHOT_BYTES)
      throw new Error("ACPX package snapshot exceeds its byte bound");
    const handle = await open(
      source,
      constants.O_RDONLY | constants.O_NOFOLLOW,
    );
    try {
      if (!same(before, await handle.stat({ bigint: true })))
        throw new Error("ACPX module changed before snapshot");
      const bytes = await readSnapshotBytes(handle, Number(before.size));
      if (
        !same(before, await handle.stat({ bigint: true })) ||
        !same(before, await lstat(source, { bigint: true }))
      ) {
        throw new Error("ACPX module changed during snapshot");
      }
      await writeFile(target, bytes, { flag: "wx", mode: 0o400 });

View on GitHub (pinned to 01ad858492)

Solutions

  1. Remove or externalize files larger than 16 MiB from the package root (ship them via another mechanism)
  2. Delete stray FIFOs/sockets/device files from the package directory
  3. Confirm the admitted root is a source package, not a build output directory containing artifacts
  4. If a large file is legitimately required, pre-process/split it below the 16 MiB bound

Example fix

// before: 40MB model shipped inside package
packages/my-app/assets/model.bin
// after: keep it out of the snapshot root
move model.bin to external storage and reference by URL
Defensive patterns

Strategy: validation

Validate before calling

for (const f of await walk(root)) {
  const st = await fs.lstat(f);
  if (!st.isFile()) throw new Error(`special file in package: ${f}`);
  if (st.size > 16 * 1024 * 1024) throw new Error(`file >16MiB: ${f}`);
}

Try / catch

try {
  await createAcpxPrivateSnapshot({ roots: [root] });
} catch (e) {
  if (e.message.includes('bounded regular file')) {
    throw new Error(`Package ${root} contains a special or >16MiB file; clean it before snapshot`);
  }
  throw e;
}

Prevention

When it happens

Trigger: copy() walks into an entry that lstat reports as not a regular file (symlink handled earlier; so FIFOs, sockets, device nodes, or directories-as-symlink leftovers) OR a regular file whose size exceeds 16n*1024n*1024n bytes.

Common situations: A package containing large bundled assets (models, wasm blobs, media) over 16 MiB; leftover Unix sockets/FIFOs in a build directory; special files created by tests inside the package tree.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/d3571e81bb38eb9e. Report an issue: GitHub.