coleam00/Archon · error · DeviceFlowError

user_fetch_failed

user_fetch_failed

Error message

GET /user returned HTTP ${res.status}

What it means

fetchGithubUser calls GET https://api.github.com/user with the access token. Any non-2xx HTTP status is converted into DeviceFlowError('user_fetch_failed') embedding the status code, so callers get one error type for profile fetch failures.

Source

Thrown at packages/core/src/github-auth/device-flow.ts:186

    client_id: clientId,
    grant_type: 'refresh_token',
    refresh_token: refreshToken,
  });
  if (data.error) throw new DeviceFlowError(data.error);
  return data;
}

/** Fetch the authenticated user's profile (id is the no-reply-email anchor). */
export async function fetchGithubUser(accessToken: string): Promise<GithubUserProfile> {
  const res = await fetch(USER_URL, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      Accept: 'application/vnd.github+json',
      'User-Agent': 'archon',
    },
  });
  if (!res.ok) {
    throw new DeviceFlowError('user_fetch_failed', `GET /user returned HTTP ${res.status}`);
  }
  const raw = (await res.json()) as {
    id: number;
    login: string;
    name?: string | null;
    email?: string | null;
  };
  return { id: raw.id, login: raw.login, name: raw.name ?? null, email: raw.email ?? null };
}

View on GitHub (pinned to 0773b97458)

Solutions

  1. Refresh or re-obtain the access token via refreshUserToken / device flow
  2. Check the embedded HTTP status: 401 means re-auth, 403 may mean rate limit — wait and retry
  3. Verify the token has required scopes for reading the user profile
  4. Check GitHub status / network connectivity if 5xx persists

Example fix

// before
const user = await fetchGithubUser(accessToken);
// after
try {
  const user = await fetchGithubUser(accessToken);
} catch (e) {
  if (e instanceof DeviceFlowError && e.code === 'user_fetch_failed' && /HTTP 401/.test(e.message)) {
    accessToken = await refreshAccessToken(clientId, refreshToken);
  } else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

if (!accessToken) throw new Error('No access token: run device flow before fetchGithubUser');

Try / catch

try { return await fetchGithubUser(token); } catch (e) { if (e instanceof DeviceFlowError && e.code === 'user_fetch_failed') { if (e.message.includes('401')) token = await reauthenticate(); else if (/403|5\d\d/.test(e.message)) await backoff(); } else throw e; }

Prevention

When it happens

Trigger: Calling fetchGithubUser(accessToken) when GitHub returns 401 (bad/expired token), 403 (rate limit or forbidden), or 5xx from the /user endpoint.

Common situations: Access token expired or revoked; token lacks the right scopes; hitting GitHub API rate limits without backoff; GitHub incident causing 5xx; corporate proxy blocking api.github.com.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/f7db0e0ee5e17a51. Report an issue: GitHub.