JuliusBrussee/caveman · error · Error
signed checksum manifest does not contain
Error message
signed checksum manifest does not contain ${artifact} What it means
After the checksum manifest passes format validation, `expectedDigest` scans it for the exact artifact filename being installed. If no line's filename matches the requested artifact, the manifest is well-formed but does not describe this artifact, so the installer throws rather than install an unverified binary. This prevents installing a binary whose hash is simply absent from the signed manifest.
Solutions
- Check the artifact filename in the error against the files listed in the release's checksums.txt.
- Pin/install a release version that actually publishes your platform's artifact.
- If your platform genuinely isn't supported, install the binary manually (package manager or build from source) and export the envVar to point at it.
- Clear stale caches (e.g. ~/.caveman) that may pin an outdated release URL, then retry.
Example fix
// before: artifact missing from manifest
await ensureBinary({ name: "caveman-mcp", envVar: "CAVEMAN_MCP_BIN" });
// after: supply a verified local binary
export CAVEMAN_MCP_BIN=/usr/local/bin/caveman-mcp Defensive patterns
Strategy: fallback
Validate before calling
const manifest = await fetch(`${release}/checksums.txt`).then(r => r.text());
if (!manifest.includes(artifactName)) {
console.warn(`${artifactName} not in release manifest; provide binary via ${envVar}`);
} Try / catch
try {
return await ensureBinary({ name, envVar });
} catch (e) {
if (String(e.message).includes("does not contain")) {
return installManuallyOrResolveFromPath(name, envVar);
}
throw e;
} Prevention
- Confirm your platform/arch has a published artifact before relying on auto-install.
- Keep installer and release versions in sync to avoid artifact-name skew.
- Document a manual-install fallback for unsupported platforms.
- Cache a known-good binary and point the envVar at it.
When it happens
Trigger: `ensureBinary()` computing `expectedDigest(checksums, artifact)` where `artifact` (the platform-specific binary filename) is not listed in checksums.txt — e.g. installer version expects `caveman-mcp-linux-x64-v1.2.0` but the release only published `v1.1.0` artifacts, or a platform (musl/arm) that was never built for that release.
Common situations: Version skew: a newer installer/CLI asking for an artifact an older release doesn't ship; unsupported platform/arch combination not in the release matrix; artifact renamed in a release while local metadata still uses the old name.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- signed checksum manifest is malformed
- adapter-specific build_sha256 values must differ
- cave_harness_artifact_digest_invalid
- cave_harness_context_ir_mismatch
- cave_harness_plan_digest_mismatch
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/fb0c3af2c953a2ff.
Report an issue: GitHub.
Appendix: source
Thrown at packages/shared/binary-installer/installer.mjs:124
return verify(
"sha256",
Buffer.from(checksums),
createPublicKey(BINARY_SIGNING_PUBKEY),
Buffer.from(bundle.messageSignature.signature, "base64"),
);
} catch {
return false;
}
}
function expectedDigest(checksums, artifact) {
for (const line of checksums.split("\n")) {
if (!line) continue;
const match = line.match(/^([a-f0-9]{64}) ([A-Za-z0-9._-]+)$/);
if (!match) throw new Error("signed checksum manifest is malformed");
if (match[2] === artifact) return match[1];
}
throw new Error(`signed checksum manifest does not contain ${artifact}`);
}
function cleanup(path) {
try {
unlinkSync(path);
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
}
async function download(url, part, timeout) {
const response = await asset(url, timeout);
if (!response.body) throw new Error("binary download failed: response body missing");
const hash = createHash("sha256");
const file = await open(part, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
const reader = response.body.getReader();
try {
while (true) {View on GitHub (pinned to 3ee70a1026)