JuliusBrussee/caveman · error
device authorization failed: HTTP
Error message
device authorization failed: HTTP ${codeResp.status} What it means
The CLI starts the RFC 8628 device-authorization flow by POSTing to the instance's device/code endpoint. If the HTTP response is not ok, it cannot obtain a device code and throws with the status code. This is a fail-fast check before any polling begins.
Solutions
- Check the printed status code: 404 usually means wrong instance/base URL, 401 a client misconfiguration, 429 too many attempts
- Verify the --instance URL points at the correct authorization server with the device-code endpoint enabled
- Wait and retry if the status is 429 or 5xx
- Inspect instance/server logs for the failing request
Example fix
// before
await cli.login({ instance: "https://wrong-host.example.com" });
// after
await cli.login({ instance: "https://auth.correct-instance.example.com" }); Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(new URL("/oauth/device/code", instance), { method: "HEAD" }).catch(() => null);
if (!probe || !probe.ok && probe.status !== 405) console.warn("Device-code endpoint not reachable at instance"); Try / catch
try { await login({ instance }) } catch (e) { const m = e.message.match(/HTTP (\d+)/); if (m && (m[1] === "429" || m[1].startsWith("5"))) await backoffThenRetry(); } Prevention
- Verify the instance URL exposes the device-code endpoint before automating logins
- Back off on 429 instead of hammering login
- Monitor authorization-server health
When it happens
Trigger: The POST to the device authorization endpoint returns a non-2xx status (401 wrong client/audience, 404 wrong path, 429 rate limit, 5xx server error) within the 5s AbortSignal timeout window.
Common situations: Wrong --instance URL pointing at a host without the device-code endpoint; identity provider misconfigured (missing device grant); server outage; rate limiting from repeated login attempts.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- device credential delivery acknowledgement failed
- device login polling failed
- awscreds: sts assume role with web identity failed
- binary download failed: HTTP
- cave_agent_tool_timeout | cave_network_error
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/da383df566ebaab2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:9681
// from the returned token, never from any local input.
// Hosted login remains gated; explicit private instances use project access.
function blockCloudLoginWhileBeta(): void {
throw new Error("Caveman Cloud platform is still in beta.");
}
async function login(argv: string[] = []) {
if (!argv.some((arg) => arg === "--instance" || arg.startsWith("--instance="))) blockCloudLoginWhileBeta();
const { noBrowser, instance } = validateLoginArgs(argv);
const baseURL = instance ?? resolveLoginBaseUrl(argv);
const codeResp = await fetch(`${baseURL}/api/v1/auth/device/code`, {
method: "POST",
redirect: "error",
headers: { "content-type": "application/json" },
body: "{}",
signal: AbortSignal.timeout(5000),
});
if (!codeResp.ok) throw new Error(`device authorization failed: HTTP ${codeResp.status}`);
const code = await codeResp.json();
if (!code.device_code) throw new Error("device authorization failed: missing device code");
const verificationURL = instance ? privateVerificationURL(code, instance) : code.verification_uri_complete ?? code.verification_uri;
console.error(`\n Authorize this device in your browser:`);
console.error(` ${verificationURL}`);
console.error(` code: ${code.user_code}\n`);
if (typeof verificationURL === "string" && shouldOpenLoginBrowser(noBrowser)) openLoginBrowser(verificationURL);
let intervalMs = Math.max(0, Number(code.interval ?? 5)) * 1000;
const deadline = Date.now() + Number(code.expires_in ?? 600) * 1000;
while (Date.now() < deadline) {
let tok: Record<string, unknown>;
let tokenStatus = 0;
let retryAfterMs = 0;
try {
const tokResp = await fetch(`${baseURL}/api/v1/auth/device/token`, {
method: "POST",View on GitHub (pinned to 3ee70a1026)