JuliusBrussee/caveman · error · Error
device authorization failed: HTTP ${codeResponse.status}
Error message
device authorization failed: HTTP ${codeResponse.status} What it means
runCavemanDeviceFlow POSTs to /api/v1/auth/device/code with a 5-second timeout to start the device authorization grant. A non-2xx response (bad gateway, auth server error, rate limit, wrong path) aborts immediately with the HTTP status embedded in this error.
Source
Thrown at packages/device-auth/src/index.ts:102
export async function runCavemanDeviceFlow(options: {
baseURL: string;
client: string;
fetch?: typeof globalThis.fetch;
signal?: AbortSignal;
sleep?: (ms: number) => Promise<void>;
onCode?: (code: DeviceCode) => void | Promise<void>;
}): Promise<DeviceGrant> {
const fetcher = options.fetch ?? globalThis.fetch;
const wait = options.sleep ?? defaultSleep;
const baseURL = options.baseURL.replace(/\/$/, "");
const codeResponse = await fetcher(`${baseURL}/api/v1/auth/device/code`, {
method: "POST",
headers: { "content-type": "application/json", "x-cave-client": options.client },
body: "{}",
signal: requestSignal(options.signal, 5000),
});
if (!codeResponse.ok) throw new Error(`device authorization failed: HTTP ${codeResponse.status}`);
const rawCode = await codeResponse.json().catch(() => null) as Partial<DeviceCode> | null;
if (rawCode === null || typeof rawCode.device_code !== "string" || rawCode.device_code === "" ||
typeof rawCode.user_code !== "string" || typeof rawCode.verification_uri !== "string" ||
typeof rawCode.expires_in !== "number" || !Number.isFinite(rawCode.expires_in) || rawCode.expires_in <= 0) {
throw new Error(`device authorization failed: ${JSON.stringify(rawCode)}`);
}
const code = rawCode as DeviceCode;
await options.onCode?.(structuredClone(code));
let intervalMs = Math.max(0, Number(code.interval ?? 5)) * 1000;
const deadline = Date.now() + code.expires_in * 1000;
while (Date.now() < deadline) {
let payload: Record<string, unknown>;
let status = 0;
let retryAfterMs = 0;
try {
const response = await fetcher(`${baseURL}/api/v1/auth/device/token`, {
method: "POST",
headers: { "content-type": "application/json", "x-cave-client": options.client },View on GitHub (pinned to df2ccd85c9)
Solutions
- Print/verify the status in the message and hit the endpoint manually: `curl -i -X POST ${baseURL}/api/v1/auth/device/code` to see the real error.
- Fix baseURL to the correct environment/API version.
- If 429, wait and retry with backoff.
- Check proxy/firewall rules if an intermediary (403/502/503) is generating the status.
- Retry during a confirmed server outage; check the provider's status page.
Example fix
// before
await runCavemanDeviceFlow({ baseURL: "https://api.example.com/v2", ... }); // v2 has no /auth/device/code
// after
await runCavemanDeviceFlow({ baseURL: "https://api.example.com/v1", ... }); // correct API version Defensive patterns
Strategy: retry
Validate before calling
const res = await fetch(`${baseURL}/api/v1/auth/device/code`, { method: "HEAD" }).catch(() => null);
if (!res || !res.ok) throw new Error(`device code endpoint not healthy (baseURL=${baseURL})`); Try / catch
try {
await runCavemanDeviceFlow(options);
} catch (e) {
if (e instanceof Error && /device authorization failed: HTTP (429|5\d\d)/.test(e.message)) {
await sleep(10000); // transient server/rate-limit issue
await runCavemanDeviceFlow(options);
} else throw e;
} Prevention
- Verify baseURL and API version before starting the flow.
- Add startup reachability checks for the auth endpoint.
- Back off on 429s instead of hammering the endpoint.
- Watch provider status pages during auth-service incidents.
When it happens
Trigger: The POST /api/v1/auth/device/code request returns any !ok status — e.g. 404 (wrong baseURL/path), 500 (server error), 429 (rate limited), 502/503 (gateway down).
Common situations: baseURL pointing to a stale or wrong environment after an API version change; auth service outage; corporate proxy returning 403/502 for the endpoint; aggressive client causing 429s.
Related errors
- tool search failed with HTTP ${response.status}
- device credential delivery acknowledgement failed (${lastErr
- device login polling failed: ${error instanceof Error ? erro
- eval evidence import failed (${response.status}): ${JSON.str
- fetch failed: too many redirects
AI-assisted analysis of JuliusBrussee/caveman@df2ccd85c9 (2026-08-31).
Data as JSON: /api/errors/06229a6bb58b97df.
Report an issue: GitHub.