JuliusBrussee/caveman · error · Error
registration failed: HTTP ${response.status}
Error message
registration failed: HTTP ${response.status} What it means
The POST to {controlURL}/api/v1/projects/{projectID}/agent-builds completed but response.ok was false, so the CLI surfaces the HTTP status verbatim. The request already passed env validation and the stale-lock gate; this is the server rejecting the registration (auth, project id, payload, or server-side error). The fetch has a 10s AbortSignal timeout, which surfaces as an AbortError, not this message.
Source
Thrown at packages/agent/src/cli.ts:502
agent_slug: lock.agent_id,
build_sha256: lock.build_sha256,
plan_sha256: lock.plan_sha256,
source_sha256: lock.source_sha256,
eval_suite_sha256: lock.eval_suite_sha256,
catalog_sha256: lock.catalog_sha256,
transform_registry_sha256: lock.runtime.transform_registry_sha256,
harness: lock.harness.id,
adapter_version: lock.harness.adapter_version,
upstream_version: lock.harness.upstream_version,
runtime_version: lock.runtime.caveman_version,
evidence_status: lock.evidence.status,
evidence_basis: lock.evidence.basis,
lock,
}),
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) {
throw new Error(`registration failed: HTTP ${response.status}`);
}
const registered = await response.json() as { id?: unknown; build_sha256?: unknown };
process.stdout.write([
`registered build: ${String(registered.build_sha256 ?? lock.build_sha256)}`,
`registration id: ${String(registered.id ?? "unavailable")}`,
"registration does not activate plan or create a savings claim",
"provider savings: not claimed",
"",
].join("\n"));
}
async function dev(args: string[]): Promise<void> {
const root = process.cwd();
const entry = args[0] ?? "src/agent.ts";
const prompt = args.slice(1).join(" ") || "Reply with one short greeting.";
const conversation = createConversation();
const sessionId = conversation.sessionId;
const interactive = args.length <= 1 && process.stdin.isTTY && process.stdout.isTTY;View on GitHub (pinned to 27d5a3981a)
Solutions
- Decode the status: 401/403 → rotate/refresh CAVE_TOKEN; 404 → verify CAVE_PROJECT_ID and CAVE_CONTROL_URL; 409 → build already registered, nothing to do; 5xx → retry or check the control plane.
- Re-check that CAVE_CONTROL_URL is the correct environment base URL with no /api suffix (the CLI appends the path).
- If 400 persists, compare CLI and control-plane versions — the payload contract may have moved; upgrade the caveman agent package.
Example fix
# before export CAVE_CONTROL_URL=https://cave.internal # wrong env (404) caveman-agent register # after export CAVE_CONTROL_URL=https://cave.example.com caveman-agent register
Defensive patterns
Strategy: retry
Validate before calling
function registrationTargetPlausible(): { ok: boolean; reason?: string } {
const url = process.env.CAVE_CONTROL_URL;
if (!url?.startsWith("https://")) return { ok: false, reason: "CAVE_CONTROL_URL must be an https base URL" };
if (!/^[A-Za-z0-9_-]+$/.test(process.env.CAVE_PROJECT_ID ?? "")) return { ok: false, reason: "CAVE_PROJECT_ID malformed" };
return { ok: true };
} Try / catch
const RETRYABLE = new Set([408, 429, 502, 503, 504]);
let attempt = 0;
while (true) {
try {
return await register(args);
} catch (error) {
const status = Number((error as Error).message.match(/HTTP (\d+)/)?.[1]);
if (RETRYABLE.has(status) && ++attempt < 4) {
await sleep(2 ** attempt * 500); // exponential backoff on 429/5xx only
continue;
}
if (status === 409) return; // already registered — treat as success
throw error; // 401/403/404 are config defects, do not retry
}
} Prevention
- Verify token freshness and correct environment (staging vs prod) for CAVE_CONTROL_URL before registering.
- Handle 409 as idempotent success — re-registering the same build_sha256 is expected after retries.
- Keep CLI and control-plane versions aligned; upgrade the agent package when the server API changes.
When it happens
Trigger: 401/403 from an invalid or expired CAVE_TOKEN; 404 from a wrong CAVE_PROJECT_ID or wrong CAVE_CONTROL_URL base path; 400/409 from an already-registered build_sha256 or schema mismatch after CLI/server version drift; 5xx from a control-plane outage.
Common situations: Expired registration token in CI; pointing CAVE_CONTROL_URL at staging while the project lives in prod (or vice versa); re-registering the same build; server API evolved beyond the CLI's payload shape.
Related errors
- binary download failed: HTTP ${response.status}
- Claude usage request failed with HTTP %d
- kms: %s request failed: %w
- register requires CAVE_CONTROL_URL, CAVE_TOKEN, and CAVE_PRO
- cave_stale_lock:registration
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/cd534fd359437340.
Report an issue: GitHub.