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
- Refresh or re-obtain the access token via refreshUserToken / device flow
- Check the embedded HTTP status: 401 means re-auth, 403 may mean rate limit — wait and retry
- Verify the token has required scopes for reading the user profile
- 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
- Refresh expired tokens proactively before calling the API
- Respect GitHub rate limits with backoff on 403/429
- Verify token scopes cover user profile reads
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
- Expected directory listing from ${url}, got a single file
- Failed to clone repository: ${safeErr.message}
- Failed to clone ${owner}/${repo}: ${unknownMsg}
- Authentication failed for ${owner}/${repo}. ${authHint}
- Failed to clone ${owner}/${repo}: ${'message' in cloneResult
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/f7db0e0ee5e17a51.
Report an issue: GitHub.