JuliusBrussee/caveman · error
[mcp_servers.caveman-cloud] exists but is not Caveman-journa
Error message
[mcp_servers.caveman-cloud] exists but is not Caveman-journaled; refusing overwrite
What it means
Codex-specific preflight: ~/.codex/config.toml contains a [mcp_servers.caveman-cloud] table, but no Caveman marker file exists for it. As with the Claude case, an unjournaled registration has unknown provenance and Caveman refuses to overwrite it during agent-native setup.
Source
Thrown at packages/cli/src/index.ts:2567
if (current && !current.equals(Buffer.from(body)) && (!previous || bytesHash(current) !== previous.after_sha256)) {
throw new Error(`${file} changed after setup; refusing to overwrite user skill edits`);
}
}
if (agent === "claude") {
const actual = claudeMcpRegistration("caveman-cloud");
const marker = readMcpServerMarker("claude", "caveman-cloud");
if (actual.present && !marker) {
throw new Error("Claude caveman-cloud MCP exists but is not Caveman-journaled; refusing overwrite");
}
if (actual.present && marker && !agentNativeCloudMcpMatches("claude", marker)) {
throw new Error("Claude caveman-cloud MCP changed after setup; refusing to overwrite user fields");
}
return;
}
const config = fileBytes(join(homedir(), ".codex", "config.toml"))?.toString("utf8") ?? "";
if (!config.includes("[mcp_servers.caveman-cloud]")) return;
if (!readMcpServerMarker("codex", "caveman-cloud")) {
throw new Error("[mcp_servers.caveman-cloud] exists but is not Caveman-journaled; refusing overwrite");
}
}
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);View on GitHub (pinned to 27d5a3981a)
Solutions
- Remove the [mcp_servers.caveman-cloud] table from ~/.codex/config.toml and re-run setup so Caveman installs and journals it
- Or rename your custom table to a different server key if you want to keep it
- Check CODEX_HOME is set as intended so setup reads/writes the config you actually use
Defensive patterns
Strategy: validation
Validate before calling
function codexCavemanCloudJournaled(): boolean {
const toml = readFileSync(join(homedir(), ".codex", "config.toml"), "utf8");
if (!toml.includes("[mcp_servers.caveman-cloud]")) return true;
return existsSync(join(cavemanHome(), "mcp", "codex.caveman-cloud.json"));
} Type guard
function isUnjournaledCodexMcpError(e: unknown): boolean {
return e instanceof Error && e.message === "[mcp_servers.caveman-cloud] exists but is not Caveman-journaled; refusing overwrite";
} Try / catch
try {
runCavemanSetup();
} catch (e) {
if (isUnjournaledCodexMcpError(e)) {
// delete the [mcp_servers.caveman-cloud] table (or rename its key), then re-run
} else throw e;
} Prevention
- Let caveman manage the caveman-cloud table in ~/.codex/config.toml
- Set CODEX_HOME deliberately and keep markers in sync with the config you use
When it happens
Trigger: Manually adding [mcp_servers.caveman-cloud] to ~/.codex/config.toml; using a pre-marker Caveman version; CODEX_HOME pointing at a config that already had the table; deleting ~/.caveman-cloud/integrations markers.
Common situations: Hand-edited codex config; config restored/synced without the caveman home; leftover from an older caveman release.
Related errors
- Claude caveman-cloud MCP exists but is not Caveman-journaled
- Claude caveman-cloud MCP changed after setup; refusing to ov
- ${agent} caveman-cloud MCP changed during interrupted setup;
- ${agent} caveman-cloud MCP changed during interrupted remova
- ${file} already exists with non-canonical content; refusing
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/978a46ae0480a16b.
Report an issue: GitHub.