mastra-ai/mastra · error

Failed to load GitHub token status (${res.status})

Error message

Failed to load GitHub token status (${res.status})

What it means

fetchGithubPatStatus fetches `${baseUrl}/web/github/pat` and throws `Failed to load GitHub token status (${res.status})` when the response is not ok. It reports that the GitHub PAT status endpoint rejected the request; only the HTTP status is included, with no server message parsing.

Source

Thrown at mastracode/factory-ui/src/ui/domains/workspaces/services/github.ts:158

/** `default` = the worker token every sandbox gets; `reviewer` = optional
 * token review-board sessions use so PR reviews come from another account. */
export type GithubPatKind = 'default' | 'reviewer';

export interface GithubPatStatus {
  configured: boolean;
  reviewerConfigured: boolean;
}

/**
 * Which GitHub Personal Access Tokens the org has configured for `gh` CLI
 * use in sandboxes. The tokens themselves never reach the browser.
 */
export async function fetchGithubPatStatus(baseUrl: string): Promise<GithubPatStatus> {
  const res = await fetch(`${baseUrl}/web/github/pat`, {
    headers: { Accept: 'application/json' },
    credentials: 'include',
  });
  if (!res.ok) throw new Error(`Failed to load GitHub token status (${res.status})`);
  return (await res.json()) as GithubPatStatus;
}

/** Save an org GitHub PAT (used only for `gh` CLI auth in sandboxes). */
export async function saveGithubPat(baseUrl: string, token: string, kind: GithubPatKind = 'default'): Promise<void> {
  const res = await fetch(`${baseUrl}/web/github/pat`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
    credentials: 'include',
    body: JSON.stringify({ token, kind }),
  });
  if (!res.ok) {
    const body = (await res.json().catch(() => undefined)) as { error?: string } | undefined;
    throw new Error(body?.error ?? `Failed to save GitHub token (${res.status})`);
  }
}

/** Remove an org GitHub PAT. */

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the status in the message: 401/403 -> re-authenticate and ensure cookies are sent (credentials: 'include' needs CORS credential support).
  2. Verify baseUrl points at the deployment that serves /web/github/pat (404 indicates a wrong base URL or missing route).
  3. Retry with React Query's built-in retry/backoff for transient 5xx/network failures.
  4. Inspect server logs for the backend error if the status is 500.

Example fix

// before
const status = await fetchGithubPatStatus(baseUrl);
// after
const { data, error } = useGithubPatStatusQuery(baseUrl);
if (error instanceof Error && /\((\d{3})\)/.test(error.message) && error.message.endsWith('(401)')) {
  redirectToLogin();
}
Defensive patterns

Strategy: retry

Validate before calling

// verify baseUrl serves the endpoint before querying
const reachable = await fetch(`${baseUrl}/web/github/pat`, { method: 'HEAD', credentials: 'include' }).then(r => r.status !== 404).catch(() => false);
if (!reachable) throw new Error('GitHub PAT endpoint unavailable: check baseUrl/deployment');

Type guard

function isGithubPatStatus(x: unknown): x is GithubPatStatus {
  return typeof x === 'object' && x !== null && 'hasToken' in x;
}

Try / catch

useQuery({
  queryKey: ['github-pat-status', baseUrl],
  queryFn: () => fetchGithubPatStatus(baseUrl),
  retry: (count, e) => {
    const m = /\((\d{3})\)/.exec((e as Error).message);
    const status = m ? Number(m[1]) : 0;
    return count < 3 && (status === 0 || status >= 500);
  },
  onError: (e: Error) => {
    if (e.message.endsWith('(401)')) redirectToLogin();
  },
});

Prevention

When it happens

Trigger: useGithubPatStatusQuery runs and the endpoint returns non-2xx: 401/403 when the session cookie is missing/expired or the caller lacks org access, 404 when the /web/github/pat route isn't deployed or baseUrl is wrong, or 5xx from a backend failure.

Common situations: Session expired while the dashboard polls token status, wrong baseUrl/proxy in dev causing 404, org without GitHub integration configured hitting an unauthorized route, or backend outage returning 502/503 through a proxy.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/70c7d1c56d482720. Report an issue: GitHub.