koala73/worldmonitor · error

HTTP

Error message

${label} HTTP ${response.status}

What it means

This is the generic non-ok fallback of assertToolFetchOk in api/mcp/billing-denial.ts: the tool's gateway fetch returned a non-ok status that is neither a billing denial (no X-Billing-Verification marker header with a known code) nor a 400 carrying safe proto violations. The message preserves the '<label> HTTP <status>' contract that dispatch's catch-all and log-severity downgrade key on. Every other classification (BillingDenialError, RpcValidationError) has already been ruled out by the time this throws.

Solutions

  1. Parse the status from the message (/ HTTP (\d+)$/) — 401/403 means auth/entitlement, 404 means route drift, 5xx means retry later
  2. For 401/403, verify the auth headers: method, full path with query string, and body must match exactly what buildAuthHeaders signed
  3. For 404, confirm the route named in the label exists in the target deployment (check docs/api/ OpenAPI or hit the path directly)
  4. For 5xx/429, retry with backoff honoring any Retry-After header
Defensive patterns

Strategy: try-catch

Type guard

function isToolHttpError(e) {
  return e instanceof Error && / HTTP \d+$/.test(e.message)
    && !(e instanceof RpcValidationError) && e.name !== 'BillingDenialError';
}
function httpStatusOf(e) { const m = e.message.match(/HTTP (\d+)$/); return m ? Number(m[1]) : null; }

Try / catch

try {
  const r = await client.callTool(name, args);
} catch (e) {
  if (isToolHttpError(e)) {
    const s = httpStatusOf(e);
    if (s >= 500 || s === 429) return retryWithBackoff(() => client.callTool(name, args), 3);
    if (s === 401 || s === 403) throw new Error('Auth/entitlement failure — refresh credentials', { cause: e });
    throw e; // 4xx other than 401/403: not retryable
  }
  throw e;
}

Prevention

When it happens

Trigger: Any tools/call whose _execute fetches a /api/... route and gets 401/403/404/409/429/500/502/503 back: an expired or mis-signed HMAC auth header (401), a lapsed entitlement without the billing marker (403), a route that does not exist in this deployment (404), or an upstream 5xx. Also fires for 400s whose body is HTML, malformed JSON, or has no sanitizable violations array.

Common situations: Signature canonicalization drift between buildAuthHeaders and the gateway (method, path, or body hash mismatch). Deploying the MCP registry and the API routes out of sync so a tool POSTs to a path that is not yet deployed. Upstream dependency outage surfacing as 502/503. Env var misconfiguration (wrong secret) producing consistent 401s.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-08-21). Data as JSON: /api/errors/c05c54be005c196f. Report an issue: GitHub.

Appendix: source

Thrown at api/mcp/billing-denial.ts:227

      const body = JSON.parse(detail) as { error?: unknown; code?: unknown } | null;
      signatureRejected = (body?.code ?? body?.error) === 'invalid_internal_mcp_signature';
    } catch {
      // Unknown or malformed bodies retain the generic status-only error.
    }
    if (signatureRejected) {
      throw new Error(`${label} HTTP 401: invalid_internal_mcp_signature`);
    }
  }
  if (preserveBackoff && (response.status === 429 || response.status === 503)) {
    throw new ToolBackoffError(response.status, response.headers?.get('Retry-After') ?? null, label);
  }
  if (response.status === 400) {
    const violations = await extractSafeRpcViolations(response);
    if (violations.length > 0) {
      throw new RpcValidationError(label, violations);
    }
  }
  throw new Error(`${label} HTTP ${response.status}`);
}

View on GitHub (pinned to 7d06c8633d)