paperclipai/paperclip · error · Error

ACPX ${agent} runtime executable digest mismatch

Error message

ACPX ${agent} runtime executable digest mismatch

What it means

After a race-free hash is computed, the sha256 digest of the executable is compared to the `expectedDigest` the runtime was provisioned with. A mismatch means the on-disk binary is not the exact bytes the installation recorded — corrupt, tampered with, or a different version. Execution is refused to guarantee supply-chain integrity of the ACPX runtime.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts:1094

    );
    const beforeIdentity = fileIdentity(before);
    const afterIdentity = fileIdentity(after);
    if (
      position !== Number(before.size) ||
      lexicalAfter === null ||
      lexicalAfter.isSymbolicLink() ||
      !lexicalAfter.isFile() ||
      !sameIdentity(fileIdentity(lexicalBefore), fileIdentity(lexicalAfter)) ||
      !sameIdentity(fileIdentity(lexicalAfter), afterIdentity) ||
      !sameIdentity(beforeIdentity, afterIdentity)
    ) {
      throw new Error(
        `ACPX ${agent} runtime executable changed while it was verified`,
      );
    }
    const digest = `sha256:${hash.digest("hex")}`;
    if (digest !== expectedDigest) {
      throw new Error(`ACPX ${agent} runtime executable digest mismatch`);
    }
    return { handle, identity: afterIdentity };
  } catch (error) {
    await handle.close();
    throw error;
  }
}

/** Fail closed where Node cannot atomically refuse a final symlink component. */
export function verifiedExecutableOpenFlags(
  platform: NodeJS.Platform,
  noFollowFlag: number | undefined,
): number {
  if (
    platform === "win32" ||
    typeof noFollowFlag !== "number" ||
    noFollowFlag === 0
  ) {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Reinstall the ACPX runtime via its official installer so bytes and recorded digest match again
  2. Confirm the expectedDigest/manifest matches the release actually installed (version skew check)
  3. Verify your download integrity independently (checksum the source archive) to rule out a corrupt transfer
  4. Stop modifying/patching the installed binary in place; apply patches through the packaging pipeline and regenerate the digest
  5. Check for disk errors (fsck/SMART) if corruption recurs across reinstalls

Example fix

// before: stale manifest from v1.2 against v1.3 binary
expectedDigest: 'sha256:abc123...'  # digest of 1.2
// after: reinstall + regenerate manifest
acpx-installer install --version 1.3
manifest.digest = sha256File('/opt/acpx/bin/acpx')  # sha256:def456...
Defensive patterns

Strategy: try-catch

Validate before calling

import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
async function sha256File(p: string): Promise<string> {
  const h = createHash('sha256');
  for await (const chunk of createReadStream(p)) h.update(chunk);
  return `sha256:${h.digest('hex')}`;
}
// compare sha256File(executablePath) against the recorded digest before starting

Try / catch

try {
  await startAcppRuntime();
} catch (e) {
  if (String(e?.message).includes('digest mismatch')) {
    // do NOT retry against the same bytes; reinstall first
    await reinstallAcpxRuntime(expectedVersion);
    await startAcppRuntime();
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: `sha256:${hash.digest('hex')}` of the opened executable differs from the expectedDigest recorded at install/verify time: the binary was modified in place, replaced by a different version, corrupted by disk/transfer errors, or the recorded digest is stale (e.g. manifest from a different release).

Common situations: Manual edits or patching of the installed binary; downloading from a mirror that served different bytes; disk corruption or incomplete copy; version skew where the installer wrote a digest for release X but release Y was extracted; users replacing the binary with a wrapper script of the same name.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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