koala73/worldmonitor · error · Error

get-country-intel-brief HTTP ${res.status}${code ? `: ${code

Error message

get-country-intel-brief HTTP ${res.status}${code ? `: ${code}` : ''}

What it means

Thrown by the get_country_intel_brief MCP tool when the downstream /api/intelligence/v1/get-country-intel-brief endpoint returned a non-OK HTTP status. Before this throw, the code checks for a BillingDenialError (re-thrown separately so billing contract is preserved), then extracts a bounded error detail (max 120 chars) from the JSON body's error field or falls back to stripped HTML/text. The message includes the HTTP status and the truncated code so Sentry titles stay bounded.

Source

Thrown at api/mcp/registry/rpc-tools.ts:1056

      });
      if (!res.ok) {
        throwIfBillingDenial(res, 'get-country-intel-brief');
        // Surface the gateway's error code in the thrown message so Sentry
        // groups the failure by root cause, not just status. Body reads are
        // best-effort; a read failure must not mask the HTTP status.
        const detail = await res.text().catch(() => '');
        let code = '';
        // `error` is usually a string (for example,
        // `invalid_internal_mcp_signature`), but stringify non-string shapes so
        // object envelopes remain readable. Bound both paths so Sentry titles
        // cannot bloat on a long body.
        try {
          const error = (JSON.parse(detail) as { error?: unknown }).error ?? '';
          code = (typeof error === 'string' ? error : JSON.stringify(error)).slice(0, 120);
        } catch {
          code = detail.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 120);
        }
        throw new Error(`get-country-intel-brief HTTP ${res.status}${code ? `: ${code}` : ''}`);
      }
      const result = await res.json() as Record<string, unknown>;
      const resultSources = collectMcpBriefSources(Array.isArray(result.sources) ? result.sources as DigestItemForBrief[] : [], 6);
      // groundingStories stays [] when the 2 s digest fetch failed above, which
      // is the honest signal: the brief was written without that grounding.
      return { ...result, sources: resultSources.length > 0 ? resultSources : sources, groundingStories };
    },
    // METHOD DRIFT: _execute POSTs above but OpenAPI declares only GET on this
    // path (verified against docs/api/IntelligenceService.openapi.json). The
    // gateway routes by path, not method, so POST works at runtime. We declare
    // GET here because OpenAPI is the parity test's source-of-truth — fixing
    // the spec to add POST (or migrating the handler to GET) is out of scope.
    _apiPaths: [
      "GET /api/intelligence/v1/get-country-intel-brief",
    ],
  },
  {
    name: 'get_country_risk',

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Read the HTTP status from the error message: 401/403 — check auth context and HMAC signing; 429 — retry with backoff; 5xx — retry after a delay (LLM provider issue); 400 — verify country_code is a valid ISO 3166-1 alpha-2 code.
  2. Retry with exponential backoff for 429 and 5xx — these are typically transient.
  3. Verify the buildAuthHeaders context (proxy_id, secret) is valid and not expired if you see 401/403.
  4. Call a different country_code to determine if the failure is country-specific or systemic.
Defensive patterns

Strategy: retry

Validate before calling

// Validate inputs and auth before calling get_country_intel_brief
if (!/^[A-Z]{2}$/.test(countryCode)) {
  throw new Error('country_code must be a valid ISO 3166-1 alpha-2 code');
}
// Verify auth context is not expired before the call
if (context.expiresAt && Date.now() > context.expiresAt) {
  throw new Error('Auth context expired; refresh before calling');
}

Type guard

function isCountryIntelBriefHttpError(e: unknown): e is { status: number } & Error {
  return e instanceof Error && /get-country-intel-brief HTTP \d+/.test(e.message);
}

Try / catch

try {
  const brief = await callMcpTool('get_country_intel_brief', { country_code: 'US' });
} catch (e) {
  if (e instanceof Error) {
    const status = e.message.match(/HTTP (\d+)/)?.[1];
    if (status === '429' || (status && Number(status) >= 500)) {
      await exponentialBackoffRetry(); // transient
    } else if (status === '401' || status === '403') {
      refreshAuthContext(); // auth issue
    } else {
      throw e; // 400 etc — input problem
    }
  } else throw e;
}

Prevention

When it happens

Trigger: The country intel brief handler returned 4xx/5xx — common causes: 401/403 (auth/HMAC failure on the gateway RPC), 429 (rate limit), 500 (LLM provider failure during brief generation), 502/504 (upstream LLM timeout), or a 400 (invalid country_code). The billing-denial path (402 with billing code) is handled earlier and never reaches this throw.

Common situations: LLM provider outage or rate limit causing the brief generation to fail; an expired or invalid MCP signature/HMAC causing 401/403; an unsupported country_code causing a 400; a gateway deployment issue where the route is temporarily unavailable.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/4ca722721e64ed87. Report an issue: GitHub.