koala73/worldmonitor · error

PUT failed: HTTP ` : ''}

Error message

PUT ${url} failed: HTTP ${response.status}${body ? ` — ${body.slice(0, 300)}` : ''}${response.status === 403 ? ' (need sntryu_ user token with project:write)' : ''}

What it means

putErrorMessageFilters PUTs the merged filters:error_messages value to Sentry project options and throws on any non-ok response, including the status, response body excerpt, and a 403 hint that a sntryu_ user token with project:write is required. It fails fast rather than proceeding to read-back verification after a failed write.

Solutions

  1. Regenerate the sntryu_ user token ensuring both project:read and project:write scopes and update SENTRY_API_TOKEN.
  2. Confirm SENTRY_ORG/SENTRY_PROJECT point at the intended project.
  3. Inspect the body excerpt in the message for a 400 validation problem with the filter text.
  4. Run with --dry-run first to confirm the merged payload before PUT.

Example fix

// before
SENTRY_API_TOKEN=sntryu_readonly_token
// after
// create user token with scopes: project:read, project:write
SENTRY_API_TOKEN=sntryu_rw_token
Defensive patterns

Strategy: try-catch

Validate before calling

const scopes = decodeJwtScopes(token); // or document token scopes at creation
if (!scopes.includes('project:write')) throw new Error('Token missing project:write');

Try / catch

try { await putErrorMessageFilters(...); } catch (err) {
  if (err.message.includes('HTTP 403')) throw new Error('Recreate token with project:read+project:write');
  throw err;
}

Prevention

When it happens

Trigger: Non-2xx from the PUT of project options: 403 because the token lacks project:write or is not a user token, 401 expired token, 404 wrong org/project, 400 payload rejected by Sentry validation.

Common situations: Read-only tokens used for a write operation, SENTRY_API_TOKEN created without the project:write scope, project slug typo, or Sentry rejecting the filter payload.

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


AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22). Data as JSON: /api/errors/db9f3c4516bd8b6e. Report an issue: GitHub.

Appendix: source

Thrown at scripts/sync-sentry-convex-probe-filters.mjs:314

 * @returns {Promise<Record<string, unknown>>}
 */
async function putErrorMessageFilters(token, org, project, filtersText) {
  const url = `${SENTRY_HOST}/api/0/projects/${org}/${project}/`;
  const response = await fetch(url, {
    method: 'PUT',
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      options: { 'filters:error_messages': filtersText },
    }),
    signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
  });
  if (!response.ok) {
    const body = await response.text();
    throw new Error(
      `PUT ${url} failed: HTTP ${response.status}`
        + (body ? ` — ${body.slice(0, 300)}` : '')
        + (response.status === 403
          ? ' (need sntryu_ user token with project:write)'
          : ''),
    );
  }
  return /** @type {Record<string, unknown>} */ (await response.json());
}

/**
 * Regenerate the committed internal probe filter list from source.
 *
 * @param {string[]} patterns
 */
function runWrite(patterns) {
  mkdirSync(dirname(COMMITTED_LIST_PATH), { recursive: true });
  writeFileSync(COMMITTED_LIST_PATH, formatCommittedFilterList(patterns), 'utf8');

View on GitHub (pinned to e586b8b4b8)