GoogleChrome/lighthouse · error · Error
Error: ${JSON.stringify(json)}
Error message
Error: ${JSON.stringify(json)} What it means
Thrown by GithubApi.createGist when the GitHub API POST /gists response parsed as JSON does not contain an 'id' field. A successful gist creation returns the gist id; any response lacking it is treated as a failure and the whole response body is stringified into the error message for diagnosis. A 401 response additionally triggers sign-out before this throw is reached.
Source
Thrown at viewer/app/src/github-api.js:82
},
},
};
const request = new Request('https://api.github.com/gists', {
method: 'POST',
headers: new Headers({Authorization: `token ${accessToken}`}),
// Stringify twice so quotes are escaped for POST request to succeed.
body: JSON.stringify(body),
});
const response = await fetch(request);
if (response.status === 401) {
this._auth.signOut();
}
const json = await response.json();
if (json.id) {
logger.log('Saved!');
return json.id;
} else {
throw new Error('Error: ' + JSON.stringify(json));
}
} finally {
this._saving = false;
}
}
/**
* Fetches a Lighthouse report from a gist.
* @param {string} id The id of a gist.
* @return {Promise<LH.Result>}
*/
getGistFileContentAsJson(id) {
logger.log('Fetching report from GitHub...', false);
return this._auth.getAccessTokenIfLoggedIn().then(accessToken => {
const headers = new Headers();
// If there's an authenticated token, include an Authorization header toView on GitHub (pinned to 9515cd4e58)
Solutions
- Inspect the stringified JSON in the error message — it typically states the problem (e.g. 'rate limit', 'Validation Failed').
- If rate-limited, wait and retry; ensure the access token has the 'gist' scope.
- Wrap createGist in try/catch and show the parsed GitHub message to the user.
Example fix
// before
const id = await githubApi.createGist(json); // unhandled on API error
// after
try {
const id = await githubApi.createGist(json);
} catch (err) {
const apiMsg = err.message; // contains JSON.stringify(githubResponse)
showUserError(`Could not save gist: ${apiMsg}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-call validation possible (server decides); validate the token scope instead. const token = await auth.getAccessToken(); // Tokens must have the 'gist' scope; verify out-of-band before saving.
Try / catch
try {
const id = await githubApi.createGist(json);
} catch (err) {
// err.message is 'Error: ' + JSON.stringify(githubResponse)
const apiError = (() => { try { return JSON.parse(err.message.replace(/^Error:\s*/, '')); } catch { return null; } })();
showUserError(apiError?.message ? `GitHub: ${apiError.message}` : err.message);
} Prevention
- Ensure the access token has the 'gist' scope before attempting to save.
- Respect GitHub rate limits; back off if you see rate-limit messages in the response.
- Keep payload size reasonable; very large reports can be rejected.
When it happens
Trigger: GitHub returns an error payload (rate-limit message, validation error, 422 unprocessable entity, permission error) instead of a gist object, so json.id is undefined.
Common situations: GitHub API rate limiting (secondary rate limits return JSON errors with HTTP 200/403); token lacking gist scope; gist content too large; transient GitHub API error responses.
Related errors
- ${resp.status} fetching gist
- Invalid API response: ${await response.text()}
- Save already in progress
- Failed to find a Lighthouse report (*${GithubApi.LH_JSON_EXT
- Invalid value: Argument 'extra-headers' must be a string
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/49bc1b77c1642319.
Report an issue: GitHub.