can1357/oh-my-pi · error · AIError.OAuthError

xAI device-code token polling failed: ${error instanceof Err

Error message

xAI device-code token polling failed: ${error instanceof Error ? error.message : String(error)}

What it means

Thrown by pollXAIDeviceToken when the fetch call to the xAI token endpoint fails during device-code polling — network errors, DNS failures, connection resets, or the built-in request timeout. The underlying error is attached as `cause`; an aborted caller signal yields LoginCancelledError instead. Distinguishing this from a 200-with-error payload matters: this is a transport-level failure of one poll iteration.

Source

Thrown at packages/ai/src/registry/oauth/xai-oauth.ts:438

	try {
		const timeoutSignal = AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS);
		response = await fetchImpl(tokenEndpoint, {
			method: "POST",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				Accept: "application/json",
			},
			body: new URLSearchParams({
				grant_type: "urn:ietf:params:oauth:grant-type:device_code",
				client_id: XAI_OAUTH_CLIENT_ID,
				device_code: deviceCode,
			}),
			redirect: "error",
			signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal,
		});
	} catch (error) {
		if (signal?.aborted) throw new AIError.LoginCancelledError();
		throw new AIError.OAuthError(
			`xAI device-code token polling failed: ${error instanceof Error ? error.message : String(error)}`,
			{ kind: "polling", provider: "xai", cause: error },
		);
	}

	let payload: unknown;
	try {
		payload = await response.json();
	} catch (error) {
		throw new AIError.OAuthError(
			`xAI device-code token polling returned invalid JSON: ${
				error instanceof Error ? error.message : String(error)
			}`,
			{ kind: "polling", provider: "xai", status: response.status, cause: error },
		);
	}

	if (response.ok) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the login — polling repeats until the code expires, and a single failed poll is usually transient; restart `omp` login if it aborts.
  2. Inspect `err.cause` for the root network error (DNS vs TLS vs timeout) and fix accordingly.
  3. Keep the machine awake and the network stable during the device-authorization window.
  4. Check proxy/VPN configuration — polls run repeatedly, so intermittent proxy failures surface here.
  5. If timeouts are frequent on your link, retry from a faster/more stable connection.

Example fix

// before: letting one bad poll kill the flow
const result = await xaiProvider.credentials();
// after: tolerate transient poll failures with backoff
let lastErr: unknown;
for (let attempt = 0; attempt < 3; attempt++) {
  try {
    return await xaiProvider.credentials();
  } catch (err) {
    if (err instanceof AIError.LoginCancelledError) throw err;
    if (err instanceof AIError.OAuthError && err.kind === "polling") {
      lastErr = err;
      await Bun.sleep(2000 * (attempt + 1));
      continue;
    }
    throw err;
  }
}
throw lastErr;
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm the token endpoint is reachable before starting the poll loop
const probe = await fetch(tokenEndpoint, { method: "OPTIONS", signal: AbortSignal.timeout(5000) }).catch(() => null);
if (!probe) {
  throw new Error("xAI token endpoint unreachable; fix connectivity before device login");
}

Try / catch

try {
  await xaiProvider.credentials();
} catch (err) {
  if (err instanceof AIError.LoginCancelledError) return;
  if (err instanceof AIError.OAuthError && err.kind === "polling" && err.cause) {
    // one failed poll is usually transient — restart the flow with backoff
    logger.warn("xAI token poll transport failure; retrying login", { cause: err.cause });
    await Bun.sleep(3000);
    return xaiProvider.credentials();
  }
  throw err;
}

Prevention

When it happens

Trigger: During `credentials` device login, a poll iteration POSTs grant_type=device_code to the token endpoint and fetchImpl rejects: offline, DNS failure, proxy unreachable, TLS reset, or TOKEN_REQUEST_TIMEOUT_MS exceeded; caller's signal not aborted.

Common situations: Network drops mid-login while the user waits to authorize in the browser; laptop sleeping between polls; VPN disconnects; proxy timeouts on long polls; DNS flakiness on repeat poll requests.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/64aa4c7a191f3129. Report an issue: GitHub.