JuliusBrussee/caveman · error · Error
Claude ANTHROPIC_BASE_URL changed after enable; refusing des
Error message
Claude ANTHROPIC_BASE_URL changed after enable; refusing destructive disable
What it means
For claude-settings, disable tolerates env.ANTHROPIC_BASE_URL only when it is absent or exactly the caveman route recorded in the journal (owned.route, e.g. <gateway>/w/claude). Any other value means you repointed Claude while the integration was active; removing the caveman env block would silently clobber your URL, so disable refuses.
Source
Thrown at packages/cli/src/index.ts:7575
const before = nativeBackupBytes(operation);
if (!current) {
if (operation.before_exists) throw new Error(`${operation.file} was removed after enable; refusing destructive disable`);
return null;
}
if (bytesHash(current) === operation.after_sha256) return before;
if (operation.kind === "claude-settings") {
const currentRoot = parseJsonFileObject(operation.file, current);
const beforeRoot = parseJsonFileObject(operation.file, before);
const currentEnv = currentRoot.env && typeof currentRoot.env === "object" && !Array.isArray(currentRoot.env)
? currentRoot.env as Record<string, unknown>
: {};
const beforeEnv = beforeRoot.env && typeof beforeRoot.env === "object" && !Array.isArray(beforeRoot.env)
? beforeRoot.env as Record<string, unknown>
: {};
const route = operation.owned?.route;
if (currentEnv.ANTHROPIC_BASE_URL !== undefined && currentEnv.ANTHROPIC_BASE_URL !== route) {
throw new Error("Claude ANTHROPIC_BASE_URL changed after enable; refusing destructive disable");
}
if (currentEnv.ANTHROPIC_BASE_URL === route) {
if (beforeEnv.ANTHROPIC_BASE_URL === undefined) delete currentEnv.ANTHROPIC_BASE_URL;
else currentEnv.ANTHROPIC_BASE_URL = beforeEnv.ANTHROPIC_BASE_URL;
}
// The first-party assertion is only ever written when the user carried no
// value of their own, so restore is a plain removal — but only while the
// value is still exactly ours; a user's later edit outlives disable.
const assume = operation.owned?.assume_first_party;
if (typeof assume === "string" && currentEnv[CLAUDE_ASSUME_FIRST_PARTY_ENV] === assume) {
delete currentEnv[CLAUDE_ASSUME_FIRST_PARTY_ENV];
}
// Symmetric to the enable-side ENABLE_TOOL_SEARCH write: only withdraw the
// value we introduced ourselves and only while it is still untouched, so a
// user who set their own afterwards keeps it.
if (beforeEnv.ENABLE_TOOL_SEARCH === undefined && currentEnv.ENABLE_TOOL_SEARCH === TOOL_SEARCH_DEFAULT) {
delete currentEnv.ENABLE_TOOL_SEARCH;
}View on GitHub (pinned to 2f49f0e1a3)
Solutions
- If the new URL is wanted: copy it out, delete the ANTHROPIC_BASE_URL key (or set it back to the caveman route), run `caveman disable claude`, then set your URL.
- If you meant to keep caveman: restore the route from the journal (owned.route in ~/.caveman/integrations/claude.json) or run `caveman doctor claude --fix`.
- For temporary rerouting prefer `caveman wrap claude` sessions over editing enabled settings.
Example fix
// before ~/.claude/settings.json
"env": { "ANTHROPIC_BASE_URL": "https://my-other-proxy" }
// after - key removed (or restored to the caveman route), then `caveman disable claude`
"env": {} Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
const settings = JSON.parse(readFileSync(`${process.env.HOME}/.claude/settings.json`, 'utf8'));
const journal = JSON.parse(readFileSync(`${process.env.HOME}/.caveman/integrations/claude.json`, 'utf8'));
const route = journal.operations.find((o: any) => o.kind === 'claude-settings')?.owned?.route;
const url = settings?.env?.ANTHROPIC_BASE_URL;
if (url !== undefined && url !== route) { console.error('ANTHROPIC_BASE_URL diverged from the caveman route; revert or delete it before disable'); process.exit(1); } Prevention
- Change routing via caveman commands, not by editing env in settings.json
- For temporary rerouting use `caveman wrap claude` instead of editing an enabled install
- Before disable, diff env.ANTHROPIC_BASE_URL against the journal's owned.route
When it happens
Trigger: `caveman disable claude` after editing ~/.claude/settings.json to set env.ANTHROPIC_BASE_URL to a different proxy or the direct API base while caveman routing was installed.
Common situations: Temporarily bypassing caveman by editing settings instead of disabling; switching to another gateway; scripts that manage the base URL in settings.json.
Related errors
- ${agent} ${event} Caveman hook changed after enable; refusin
- Claude caveman MCP entry changed after enable; refusing dest
- Claude caveman-cloud MCP changed after setup; refusing to ov
- ${operation.file} was removed after enable; refusing destruc
- Gemini caveman MCP entry changed after enable; refusing dest
AI-assisted analysis of JuliusBrussee/caveman@2f49f0e1a3 (2026-08-18).
Data as JSON: /api/errors/f88fcdbae9dd5c68.
Report an issue: GitHub.