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
- Reinstall the ACPX runtime via its official installer so bytes and recorded digest match again
- Confirm the expectedDigest/manifest matches the release actually installed (version skew check)
- Verify your download integrity independently (checksum the source archive) to rule out a corrupt transfer
- Stop modifying/patching the installed binary in place; apply patches through the packaging pipeline and regenerate the digest
- 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
- Never edit or patch the installed binary in place; regenerate the digest through the packaging pipeline
- Keep the digest manifest and the binary in lockstep (same release/version)
- Verify download checksums at install time before recording the digest
- On mismatch, reinstall; never regenerate the digest to accept arbitrary bytes
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
- Materialized OpenCode executable digest mismatch
- Public viewer asset differs from trusted build: ${file}
- ACPX snapshot manifest digest mismatch
- ACPX private snapshot digest mismatch
- runnerd digest mismatch: expected ${request.runnerd.sha256},
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/9aa329412de90a62.
Report an issue: GitHub.