JuliusBrussee/caveman · error · Error
failed skill postflight
Error message
${skill.file} failed skill postflight What it means
Thrown at the end of verifyAgentNativeBundle when a skill file recorded in the agent-native bundle journal is missing or its hash no longer equals the after_sha256 captured at setup. It certifies that every delivered skill file is still intact right after installation.
Solutions
- Re-run `caveman setup --agent-native <agent>` to rewrite the skill files and re-verify.
- Exclude the agent's config/skills directories from file-sync or antivirus real-time scanning.
- Check for concurrent caveman/agent processes and ensure only one setup runs at a time.
- Verify free disk space and filesystem writability for the skills directory.
Example fix
// before: sync tool rewrites files mid-setup ~/Library/CloudStorage/... synced skills dir // after: relocate agent config out of synced storage or pause sync during setup $ caveman setup --agent-native claude
Defensive patterns
Strategy: validation
Validate before calling
const current = fileBytes(skill.file);
if (!current || bytesHash(current) !== skill.after_sha256) {
console.error(`${skill.file} missing or modified; re-run setup`);
} Try / catch
try {
verifyAgentNativeBundle(agent, journal, cloudMcp);
} catch (err) {
if (/failed skill postflight/.test((err as Error).message)) {
console.error("Skill file changed during setup; re-running");
}
} Prevention
- Exclude agent config/skills directories from file-sync and antivirus scanning.
- Run only one caveman setup at a time.
- Ensure adequate disk space before setup.
When it happens
Trigger: During setup postflight, fileBytes(skill.file) returns nothing (file deleted) or bytesHash(current) !== skill.after_sha256 — e.g. the file was overwritten between write and verification, or the write silently failed.
Common situations: Antivirus or sync tools (Dropbox/iCloud) modified or locked the skill file immediately after writing; two setup runs raced; disk-full truncated the file; the agent overwrote its skills directory on startup.
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
- changed after setup; refusing destructive bundle removal
- caveman-cloud MCP postflight mismatch
- caveman-cloud MCP registration failed exact postflight
- native integration postflight is
- caveman-cloud MCP changed after setup; refusing destructive…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/75f190639ed9fd92.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2916
before_base64: originals.get(file) ?? null,
after_sha256: bytesHash(Buffer.from(body)),
};
});
}
function verifyAgentNativeBundle(agent: "claude" | "codex", journal: AgentNativeBundleJournal, cloudMcp: { command: string; args: string[] }): void {
const status = nativeIntegrationStatus(agent);
if (status.state !== "installed") throw new Error(`${agent} native integration postflight is ${status.state}`);
const marker = readMcpServerMarker(agent, "caveman-cloud");
if (!marker || marker.command !== cloudMcp.command || JSON.stringify(marker.args) !== JSON.stringify(cloudMcp.args)) {
throw new Error(`${agent} caveman-cloud MCP postflight mismatch`);
}
if (!agentNativeCloudMcpMatches(agent, cloudMcp)) {
throw new Error(`${agent} caveman-cloud MCP registration failed exact postflight`);
}
for (const skill of journal.skills) {
const current = fileBytes(skill.file);
if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} failed skill postflight`);
}
}
function removeAgentNativeBundle(agent: "claude" | "codex"): void {
recoverPendingAgentNativeRemoval(agent);
recoverPendingAgentNativeBundle(agent);
const journal = readAgentNativeBundleJournal(agent);
if (!journal) {
process.stderr.write(`${mark("warn")} ${agent}: no agent-native bundle journal found\n`);
return;
}
for (const skill of journal.skills) {
const current = fileBytes(skill.file);
if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} changed after setup; refusing destructive bundle removal`);
}
const marker = readMcpServerMarker(agent, "caveman-cloud");
if (!sameMcpCommand(marker, journal.cloud_mcp) || !agentNativeCloudMcpMatches(agent, journal.cloud_mcp)) {
throw new Error(`${agent} caveman-cloud MCP changed after setup; refusing destructive bundle removal`);View on GitHub (pinned to 3ee70a1026)