koala73/worldmonitor · error
GET failed: HTTP ` : ''}
Error message
GET ${url} failed: HTTP ${response.status}${body ? ` — ${body.slice(0, 300)}` : ''}${response.status === 403 ? ' (need sntryu_ user token with project:read)' : ''} What it means
fetchProjectOptions performs an authenticated GET of the Sentry project options and throws when the response is not ok, embedding the status code, up to 300 chars of the response body, and a hint for 403 that a sntryu_ user token with project:read scope is required. It surfaces the real Sentry API failure instead of failing later with a confusing parse error.
Solutions
- Create a sntryu_ user token with project:read (and project:write) scope and set it as SENTRY_API_TOKEN.
- Verify SENTRY_ORG and SENTRY_PROJECT slugs match the Sentry URL.
- Check the embedded response body in the error for Sentry's specific message (rate limit, auth, not found).
- If 429, wait and retry after the rate-limit window.
Example fix
// before SENTRY_AUTH_TOKEN=sntrys_... // org token, no project:read // after SENTRY_API_TOKEN=sntryu_... // user token with project:read and project:write
Defensive patterns
Strategy: try-catch
Validate before calling
if (!process.env.SENTRY_API_TOKEN?.startsWith('sntryu_')) throw new Error('Need sntryu_ user token with project:read'); Try / catch
try { await fetchProjectOptions(...); } catch (err) {
if (err.message.includes('HTTP 403')) console.error('Token lacks project:read — create a sntryu_ user token');
else if (err.message.includes('HTTP 429')) scheduleRetry();
else throw err;
} Prevention
- Use a sntryu_ user token with project:read, not org-level CI tokens.
- Verify SENTRY_ORG/SENTRY_PROJECT slugs against the Sentry URL before running.
- Dry-run the GET with curl first to confirm token access.
When it happens
Trigger: Any non-2xx from GET of the Sentry project options endpoint: 401 invalid/expired token, 403 token lacking project:read (or is an org token instead of sntryu_ user token), 404 wrong org/project slug, 429 rate limited.
Common situations: Using SENTRY_AUTH_TOKEN from CI (org-level) instead of a user token, missing project:read scope, mistyped SENTRY_ORG/SENTRY_PROJECT, or an expired session token.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- PUT failed: HTTP ` : ''}
- Sentry issues request failed: HTTP
- Cloudflare Radar API error
- Convex embed key validation unavailable: http
- Embed map frame request failed
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22).
Data as JSON: /api/errors/da9b65f58ff3cb24.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/sync-sentry-convex-probe-filters.mjs:277
}
/**
* GET project options from Sentry (includes `filters:error_messages`).
*
* @param {string} token
* @param {string} org
* @param {string} project
* @returns {Promise<Record<string, unknown>>}
*/
async function fetchProjectOptions(token, org, project) {
const url = `${SENTRY_HOST}/api/0/projects/${org}/${project}/`;
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
});
if (!response.ok) {
const body = await response.text();
throw new Error(
`GET ${url} failed: HTTP ${response.status}`
+ (body ? ` — ${body.slice(0, 300)}` : '')
+ (response.status === 403
? ' (need sntryu_ user token with project:read)'
: ''),
);
}
return /** @type {Record<string, unknown>} */ (await response.json());
}
/**
* PUT `filters:error_messages` on the Sentry project (merge-safe caller must
* pass the full newline-joined option string).
*
* @param {string} token
* @param {string} org
* @param {string} project
* @param {string} filtersTextView on GitHub (pinned to e586b8b4b8)