JuliusBrussee/caveman · error · Error
caveman-cloud MCP postflight mismatch
Error message
${agent} caveman-cloud MCP postflight mismatch What it means
Thrown by verifyAgentNativeBundle when the caveman-cloud MCP server marker read back from the agent's config either does not exist or does not exactly match the expected command and args that were supposed to be registered during setup. This is a postflight consistency check on the agent's MCP configuration.
Solutions
- Re-run `caveman setup --agent-native <agent>` to rewrite the caveman-cloud MCP entry.
- Inspect the agent's MCP config for the caveman-cloud entry and remove stale/conflicting registrations manually, then re-run setup.
- Confirm no other tool (or an older caveman version) is managing the caveman-cloud server name in that agent's config.
- Compare the marker's command/args with the expected values to spot path drift (e.g. node version path changed) and update.
Example fix
// before: stale marker from an old install
"caveman-cloud": { "command": "/old/path/node", "args": ["old-cli.mjs"] }
// after: re-run setup or correct the entry
"caveman-cloud": { "command": "/current/path/node", "args": ["/current/caveman.mjs", "serve-cloud"] } Defensive patterns
Strategy: validation
Validate before calling
const marker = readMcpServerMarker(agent, "caveman-cloud");
if (!marker || marker.command !== expected.command || JSON.stringify(marker.args) !== JSON.stringify(expected.args)) {
console.error("caveman-cloud MCP entry missing or stale; re-run caveman setup --agent-native " + agent);
} Type guard
function hasCloudMarker(m: unknown): m is { command: string; args: string[] } {
return !!m && typeof m === "object" && typeof (m as any).command === "string" && Array.isArray((m as any).args);
} Try / catch
try {
verifyAgentNativeBundle(agent, journal, cloudMcp);
} catch (err) {
if (/(postflight mismatch)/.test((err as Error).message)) {
console.error("MCP entry drifted; re-running setup to rewrite it");
}
} Prevention
- Don't hand-edit the agent's MCP config while caveman manages the caveman-cloud entry.
- Prevent other MCP managers from owning the same server name.
- Re-run setup after agent CLI upgrades.
When it happens
Trigger: After setup, readMcpServerMarker(agent, "caveman-cloud") returns null, or the marker's command/args differ from the cloudMcp {command,args} the setup intended to write — e.g. the agent rewrote its config, or a stale entry points at an old command path.
Common situations: The agent CLI normalized or rewrote its MCP config on startup; a different tool also manages the same MCP server name and overwrote it; switching between dev/staging cloud commands left a stale marker; manual edits to the agent config.
Related errors
- caveman-cloud MCP changed after setup; refusing destructive…
- caveman-cloud MCP registration failed exact postflight
- native integration postflight is
- Claude caveman MCP entry changed after enable; refusing…
- Gemini caveman MCP entry changed after enable; refusing…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/374a422673bc0b08.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2909
function installAgentNativeBundleSkills(agent: "claude" | "codex", journal: AgentNativeBundleJournal): void {
const originals = new Map(journal.skills.map((skill) => [skill.file, skill.before_base64]));
journal.skills = agentNativeSkillFiles(agent).map(({ file, body }) => {
mkdirSync(dirname(file), { recursive: true });
atomicWriteFile(file, Buffer.from(body));
return {
file,
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;
}View on GitHub (pinned to 3ee70a1026)