{"record":{"id":"38c80d169b8e6010","repo":"decolua/9router","slug":"grok-cli-device-code-request-failed-error","errorCode":null,"errorMessage":"`Grok CLI device code request failed: ${error}`","messagePattern":"`Grok CLI device code request failed: (.+?)`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/providers/grok-cli.js","lineNumber":28,"sourceCode":"      client_id: config.clientId,\n      scope: config.scope,\n    });\n    // Official CLI sends referrer=grok-build\n    if (config.referrer) body.set(\"referrer\", config.referrer);\n\n    const response = await fetch(config.deviceCodeUrl, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\",\n        Accept: \"application/json\",\n        \"User-Agent\": \"grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)\",\n      },\n      body,\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Grok CLI device code request failed: ${error}`);\n    }\n\n    return await response.json();\n  },\n  pollToken: async (config, deviceCode) => {\n    const response = await fetch(config.tokenUrl, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\",\n        Accept: \"application/json\",\n        \"User-Agent\": \"grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)\",\n      },\n      body: new URLSearchParams({\n        grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n        device_code: deviceCode,\n        client_id: config.clientId,\n      }),\n    });","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/providers/grok-cli.js#L10-L46","documentation":"Grok CLI device-flow bootstrap: the POST to xAI's device-code endpoint returned a non-2xx status; the body text is thrown inside this Error. The device flow cannot start — no device_code or verification_uri is produced and polling never begins.","triggerScenarios":"Calling startDeviceFlow for grok-cli when the device-code endpoint replies !response.ok — 401/403 bad client_id, 404 after xAI endpoint changes, 429 rate limit from repeated logins, or network/proxy failures returning error pages.","commonSituations":"xAI relocated or gated the device endpoint; stale client_id in provider config; aggressive retry loops hitting 429; corporate proxy blocking the domain; xAI outage.","solutions":["Read the body text for status-specific causes (invalid client vs rate limit vs 404).","Verify the xAI device-code URL and client_id against the current grok-cli upstream.","Wait and retry with backoff if the response indicates 429 rate limiting.","Test general reachability of the xAI endpoint (curl) to rule out proxy/DNS issues."],"exampleFix":"// before\nif (!response.ok) {\n  const error = await response.text();\n  throw new Error(`Grok CLI device code request failed: ${error}`);\n}\n// after\nif (!response.ok) {\n  const error = await response.text();\n  throw new Error(`Grok CLI device code request failed (HTTP ${response.status}): ${error}`);\n}","handlingStrategy":"retry","validationCode":"// Precheck before requesting a device code\nif (!config.clientId) throw new Error(\"Grok CLI client_id missing\");\nconst reachable = await fetch(config.deviceCodeUrl, { method: \"OPTIONS\" })\n  .then(r => r.status < 500).catch(() => false);\nif (!reachable) throw new Error(\"xAI device-code endpoint unreachable\");","typeGuard":"function hasValidGrokDeviceCode(v) {\n  return !!v && typeof v === \"object\" &&\n    typeof v.device_code === \"string\" &&\n    (typeof v.verification_uri === \"string\" || typeof v.verification_url === \"string\");\n}","tryCatchPattern":"try {\n  const dc = await grokProvider.startDeviceFlow();\n} catch (err) {\n  if (String(err.message).includes(\"Grok CLI device code request failed\")) {\n    if (String(err.message).includes(\"429\")) {\n      await waitMs(30_000); // rate limited — back off before retrying\n    }\n    await retryWithBackoff(() => grokProvider.startDeviceFlow(), { retries: 3 });\n  } else throw err;\n}","preventionTips":["Back off on 429 instead of tight retry loops that worsen rate limiting.","Keep the device-code URL and client_id synced with the current grok-cli upstream.","Allow-list the xAI domain on corporate proxies before first login.","Wrap the request in a timeout so dead endpoints fail fast and predictably."],"tags":["oauth","device-flow","xai","http-error"],"backgroundTag":"oauth-device-flow-request-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}