mastra-ai/mastra · error
Failed to list repos (${res.status})
Error message
Failed to list repos (${res.status}) What it means
listGithubRepos GETs `${baseUrl}/web/github/repos` (optionally with `?q=`) and throws this error when the response is not ok, before attempting to parse `{ repos: GithubRepo[] }`. It signals the repo listing could not be retrieved for the user's GitHub App installations.
Source
Thrown at mastracode/factory-ui/src/ui/domains/workspaces/services/github.ts:190
throw new Error(body?.error ?? `Failed to save GitHub token (${res.status})`);
}
}
/** Remove an org GitHub PAT. */
export async function deleteGithubPat(baseUrl: string, kind: GithubPatKind = 'default'): Promise<void> {
const res = await fetch(`${baseUrl}/web/github/pat?kind=${kind}`, {
method: 'DELETE',
headers: { Accept: 'application/json' },
credentials: 'include',
});
if (!res.ok) throw new Error(`Failed to remove GitHub token (${res.status})`);
}
/** List repos across the user's installations, optionally filtered by query. */
export async function listGithubRepos(baseUrl: string, query?: string): Promise<GithubRepo[]> {
const url = query ? `${baseUrl}/web/github/repos?q=${encodeURIComponent(query)}` : `${baseUrl}/web/github/repos`;
const res = await fetch(url, { headers: { Accept: 'application/json' }, credentials: 'include' });
if (!res.ok) throw new Error(`Failed to list repos (${res.status})`);
const body = (await res.json()) as { repos: GithubRepo[] };
return body.repos;
}
/** The GitHub source-control integration id registered on the server. */
const GITHUB_INTEGRATION_ID = 'github';
/** A Factory project row from `/web/factory/projects`. */
export interface FactoryProjectPayload {
id: string;
name: string;
/** Org-wide default model for factory runs; null when unset. */
defaultModelId?: string | null;
/** Whether new Slack sessions create Work-board items for this Factory. */
slackWorkItemsEnabled?: boolean;
/** Whether Factory rules may start agent runs without someone asking for them. */
autoRunEnabled?: boolean;
}View on GitHub (pinned to 75dd419e61)
Solutions
- Check the status: 401/403 → reinstall/re-authorize the GitHub App or re-login; 429 → back off and retry after the rate-limit window
- Handle the throw in the query hook (React Query will retry automatically) and show an empty/error state instead of crashing
- Verify the installation is still active for the target org on GitHub → Settings → Applications
- Confirm server egress to api.github.com is allowed in self-hosted deployments
- Retry with a narrower `q` if a broad query correlates with rate-limit hits
Example fix
// before
const repos = await listGithubRepos(baseUrl, query);
// after
const repos = await listGithubRepos(baseUrl, query).catch((e) => {
if (/\(429\)/.test(e.message)) return []; // rate-limited: show empty state
throw e;
}); Defensive patterns
Strategy: retry
Validate before calling
function canListRepos(): boolean {
return typeof baseUrl === 'string' && baseUrl.length > 0; // listing needs no client-side input; ensure a query hook is mounted with an authenticated session
} Type guard
function isGithubRepoList(b: unknown): b is { repos: GithubRepo[] } {
return typeof b === 'object' && b !== null && Array.isArray((b as { repos?: unknown }).repos);
} Try / catch
useQuery({
queryKey: ['github','repos', query],
queryFn: () => listGithubRepos(baseUrl, query),
retry: (count, err) => /\((429|5\d\d)\)/.test(err.message) && count < 3,
staleTime: 60_000,
}); Prevention
- Use React Query with conditional retry on 429/5xx only
- Cache repo lists (staleTime) to reduce GitHub rate-limit exposure
- Check GitHub App installation status before offering repo pickers
- Handle the error state in the UI with a retry button, not a crash
- Alert on server-side GitHub API failures if self-hosting (egress/rate limits)
When it happens
Trigger: Non-ok response from GET /web/github/repos: 401 when no GitHub App installation is linked or the session is unauthenticated, 403 insufficient permissions/installation revoked, 429 GitHub rate limit proxied by the server, 502/504 when the server's call to the GitHub API fails or times out.
Common situations: GitHub App installation uninstalled or suspended; token expired server-side; searching repos while GitHub API rate limit is exhausted; server cannot reach GitHub (network egress blocked in self-hosted environments).
Related errors
- ${body?.error} or Failed to save GitHub token (${res.status}
- Failed to remove GitHub token (${res.status})
- request failed with status ${response.status}: ${responseTex
- GitHub OAuth token exchange failed: ${res.status}
- await extractError(res)
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/fc33fdfe5310bc70.
Report an issue: GitHub.