{"record":{"id":"cd534fd359437340","repo":"JuliusBrussee/caveman","slug":"registration-failed-http-response-status","errorCode":null,"errorMessage":"registration failed: HTTP ${response.status}","messagePattern":"registration failed: HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":502,"sourceCode":"      agent_slug: lock.agent_id,\n      build_sha256: lock.build_sha256,\n      plan_sha256: lock.plan_sha256,\n      source_sha256: lock.source_sha256,\n      eval_suite_sha256: lock.eval_suite_sha256,\n      catalog_sha256: lock.catalog_sha256,\n      transform_registry_sha256: lock.runtime.transform_registry_sha256,\n      harness: lock.harness.id,\n      adapter_version: lock.harness.adapter_version,\n      upstream_version: lock.harness.upstream_version,\n      runtime_version: lock.runtime.caveman_version,\n      evidence_status: lock.evidence.status,\n      evidence_basis: lock.evidence.basis,\n      lock,\n    }),\n    signal: AbortSignal.timeout(10_000),\n  });\n  if (!response.ok) {\n    throw new Error(`registration failed: HTTP ${response.status}`);\n  }\n  const registered = await response.json() as { id?: unknown; build_sha256?: unknown };\n  process.stdout.write([\n    `registered build: ${String(registered.build_sha256 ?? lock.build_sha256)}`,\n    `registration id: ${String(registered.id ?? \"unavailable\")}`,\n    \"registration does not activate plan or create a savings claim\",\n    \"provider savings: not claimed\",\n    \"\",\n  ].join(\"\\n\"));\n}\n\nasync function dev(args: string[]): Promise<void> {\n  const root = process.cwd();\n  const entry = args[0] ?? \"src/agent.ts\";\n  const prompt = args.slice(1).join(\" \") || \"Reply with one short greeting.\";\n  const conversation = createConversation();\n  const sessionId = conversation.sessionId;\n  const interactive = args.length <= 1 && process.stdin.isTTY && process.stdout.isTTY;","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/cli.ts#L484-L520","documentation":"After register posts the lock to `${CAVE_CONTROL_URL}/api/v1/projects/{id}/agent-builds` (with a 10s AbortSignal timeout), any non-2xx HTTP status is converted into this generic error containing the status code. The control plane rejected the registration request for a reason the CLI does not interpret.","triggerScenarios":"The fetch to the agent-builds endpoint returns response.ok === false — e.g. 401 for an invalid/expired CAVE_TOKEN, 403 for a token lacking access to CAVE_PROJECT_ID, 404 for a wrong project id or control URL path, 5xx for control-plane downtime.","commonSituations":"Rotated or revoked tokens not updated in CI; project id from a different environment; control-plane URL pointing at staging while the token is for production; control plane temporarily down.","solutions":["Read the status: 401/403 → check CAVE_TOKEN validity and project access; 404 → verify CAVE_PROJECT_ID and CAVE_CONTROL_URL; 5xx → retry later.","Confirm the token has permission for this project in the control plane UI.","Curl the same endpoint manually with `Authorization: Bearer $CAVE_TOKEN` to see the response body, which the CLI discards.","Check control-plane health/status page if 5xx persists."],"exampleFix":"// before\ncaveman register  # registration failed: HTTP 401\n// after\nexport CAVE_TOKEN=<freshly-issued-token>\ncaveman register","handlingStrategy":"retry","validationCode":"const res = await fetch(`${process.env.CAVE_CONTROL_URL}/api/v1/health`, {\n  headers: { authorization: `Bearer ${process.env.CAVE_TOKEN}` },\n});\nif (res.status === 401 || res.status === 403) throw new Error(\"CAVE_TOKEN invalid for this project\");","typeGuard":null,"tryCatchPattern":"try {\n  await register();\n} catch (err) {\n  const m = /registration failed: HTTP (\\d+)/.exec(String(err?.message));\n  if (m) {\n    const status = Number(m[1]);\n    if (status >= 500) await register();            // retry transient\n    else console.error(`Control plane rejected: ${status}; check token/project id`);\n  } else throw err;\n}","preventionTips":["Pre-flight the control plane with a cheap authenticated request before registering.","Rotate tokens on a schedule and update CI secrets promptly.","Verify CAVE_PROJECT_ID exists in the target environment (staging vs production).","Add status-specific handling rather than treating all failures alike."],"tags":["http","network","api"],"backgroundTag":"http-error-response","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}