can1357/oh-my-pi · error · Error
Failed to fetch GitHub release metadata: ${response.statusTe
Error message
Failed to fetch GitHub release metadata: ${response.statusText} What it means
Thrown by getReleaseBinaryAsset in packages/coding-agent/src/cli/update-cli.ts when the GitHub REST releases API responds with a non-OK status that is not the already-handled 403/429 rate-limit case. The updater needs release metadata (assets, digests) to locate the correct binary; without a 2xx response it cannot proceed. The HTTP statusText is embedded so the developer can see why GitHub rejected the request.
Source
Thrown at packages/coding-agent/src/cli/update-cli.ts:277
try {
response = await fetchImpl(`${GITHUB_API}/repos/${REPO}/releases/tags/${encodeURIComponent(tag)}`, {
headers,
signal: withTimeoutSignal(RELEASE_METADATA_TIMEOUT_MS),
});
} catch (err) {
if (isTimeoutError(err)) {
throw new Error("Timed out fetching GitHub release metadata after 30s", { cause: err });
}
if (isUnsupportedProxyError(err)) throw new Error(unsupportedProxyMessage(), { cause: err });
throw err;
}
if ((response.status === 403 && !githubToken) || response.status === 429) {
throw new Error(
"GitHub API rate limit exceeded while fetching release metadata; retry later or set GITHUB_TOKEN or GH_TOKEN",
);
}
if (!response.ok) {
throw new Error(`Failed to fetch GitHub release metadata: ${response.statusText}`);
}
return resolveReleaseBinaryAsset(await response.json(), tag, binaryName, { allowPrerelease });
}
export interface VerifiedBinaryDownloadOptions {
url: string;
targetPath: string;
expectedSize: number;
expectedDigest: string;
fetchImpl?: Fetch;
}
/**
* Download a binary and verify its GitHub-reported size and SHA-256 digest.
*/
export async function downloadVerifiedBinary(options: VerifiedBinaryDownloadOptions): Promise<void> {
const fetchImpl = options.fetchImpl ?? fetch;View on GitHub (pinned to 9690622007)
Solutions
- Verify the release/tag actually exists on the repo the updater targets (e.g. check https://github.com/<owner>/<repo>/releases).
- If GITHUB_TOKEN or GH_TOKEN is set, validate it: `gh api user` or `curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com` — replace or unset if invalid.
- If the error is transient (5xx), wait and retry the update later.
- Check https://www.githubstatus.com for ongoing GitHub API incidents.
Example fix
// before: expired token in shell profile export GITHUB_TOKEN=ghp_oldexpiredtoken // after unset GITHUB_TOKEN # or export GITHUB_TOKEN=$(gh auth token)
Defensive patterns
Strategy: try-catch
Validate before calling
const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
if (token) {
const res = await fetch("https://api.github.com/user", { headers: { Authorization: `Bearer ${token}` } });
if (!res.ok) console.warn("GITHUB_TOKEN is invalid; unset it before updating");
} Type guard
function isGitHubApiFailure(err: unknown): err is Error & { message: string } {
return err instanceof Error && err.message.startsWith("Failed to fetch GitHub release metadata");
} Try / catch
try {
await runUpdate();
} catch (err) {
if (isGitHubApiFailure(err)) {
// inspect statusText in err.message; wait for GitHub incident or fix GITHUB_TOKEN, then retry
} else throw err;
} Prevention
- Keep GITHUB_TOKEN fresh (use `gh auth token`) or unset it when not needed
- Check githubstatus.com before large update rollouts
- Pin updates to tags you have verified exist in the releases page
When it happens
Trigger: Any non-ok GitHub API response during `omp update`: 404 when the resolved release tag or release object does not exist, 401 when GITHUB_TOKEN/GH_TOKEN is set but invalid or expired, 5xx when GitHub is having an incident, or 403 with a token set (rate-limit-with-token branch only handles 403 without a token).
Common situations: Running an update against a fork or private repo where the release is not published; a stale/expired GitHub PAT in the environment; GitHub status degradation; requesting a --canary tag that was deleted.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Download failed: ${response.statusText}
- GitHub API error: ${response.status}
- Devin API error ${response.status} ${response.statusText}: $
- Failed to initiate device authorization: ${initiateResponse.
- GitHub release ${expectedTag} has no asset list
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8dddada686037de5.
Report an issue: GitHub.