GoogleChrome/lighthouse · error
Invalid API response: ${await response.text()}
Error message
Invalid API response: ${await response.text()} What it means
Thrown by fetchAndInjectComments() when the GitHub API response for an issue's comments URL is not ok (non-2xx). This is one of several identical guards in the issue-download script; this specific one fetches the main `/issues/{n}/comments` endpoint.
Source
Thrown at core/scripts/internal-analysis/download-issues.js:69
}
/**
* @param {AugmentedGitHubIssue} issue
*/
async function fetchAndInjectEvents(issue) {
process.stdout.write(`Fetching ${issue.events_url}...\n`);
const response = await fetch(issue.events_url, {headers: HEADERS});
const events = await response.json();
issue.events = events;
}
/**
* @param {AugmentedGitHubIssue} issue
*/
async function fetchAndInjectComments(issue) {
process.stdout.write(`Fetching ${issue.comments_url}...\n`);
const response = await fetch(issue.comments_url, {headers: HEADERS});
if (!response.ok) throw new Error(`Invalid API response: ${await response.text()}`);
const comments = await response.json();
issue.comments = comments;
if (!Array.isArray(issue.comments)) {
console.warn('Comments was not an array', issue.comments);
issue.comments = [];
}
if (issue.pull_request) {
const prCommentsUrl = issue.comments_url
.replace('/issues/', '/pulls/')
.replace('/comments', '/reviews');
process.stdout.write(`Fetching ${prCommentsUrl}...\n`);
const response = await fetch(prCommentsUrl, {headers: HEADERS});
if (!response.ok) throw new Error(`Invalid API response: ${await response.text()}`);
const comments = await response.json();
issue.comments = issue.comments.concat(comments);
}
}View on GitHub (pinned to 9515cd4e58)
Solutions
- Set a valid GITHUB_TOKEN with repo/public_repo read scope in the environment.
- If rate-limited (403 with X-RateLimit-Remaining: 0), wait and retry or reduce request volume.
- Verify the issue URL is correct and the repo exists.
Example fix
// before
const response = await fetch(issue.comments_url, {headers: HEADERS});
// after
if (!process.env.GITHUB_TOKEN) throw new Error('Set GITHUB_TOKEN');
const response = await fetch(issue.comments_url, {headers: HEADERS});
if (!response.ok) throw new Error(`Invalid API response: ${await response.text()}`); Defensive patterns
Strategy: retry
Validate before calling
async function safeFetchJson(url, headers) {
for (let attempt = 0; attempt < 3; attempt++) {
const res = await fetch(url, {headers});
if (res.status === 403 && res.headers.get('x-ratelimit-remaining') === '0') {
const reset = Number(res.headers.get('x-ratelimit-reset')) * 1000;
await new Promise(r => setTimeout(r, Math.max(0, reset - Date.now())));
continue;
}
if (res.ok) return res.json();
throw new Error(`Invalid API response: ${await res.text()}`);
}
throw new Error('rate limited after retries');
} Try / catch
try {
await fetchAndInjectComments(issue);
} catch (e) {
if (/rate limit/i.test(e.message)) { /* back off and retry */ }
else throw e;
} Prevention
- Always set GITHUB_TOKEN before running download-issues.
- Check rate limit status before bulk-fetching.
- Handle 403 with X-RateLimit-Remaining: 0 by sleeping until reset.
When it happens
Trigger: Calling download-issues when GitHub returns 401 (bad/missing token), 403 (rate limit or forbidden), or 404 (issue deleted/moved).
Common situations: Missing or expired GITHUB_TOKEN env var; hitting GitHub's secondary rate limits; the issue or repo has been deleted.
Related errors
- Error: ${JSON.stringify(json)}
- ${resp.status} fetching gist
- Invalid value: Argument 'extra-headers' must be a string
- NO_TTI_NETWORK_IDLE_PERIOD
- error fetching ${url}: ${response.status} ${response.statusT
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/fff32eb6575ec3ec.
Report an issue: GitHub.