koala73/worldmonitor · error

POST HTTP

Error message

${method} POST HTTP ${postResp.status}

What it means

Thrown by SseSession.send when the POST of a JSON-RPC message to the server-advertised endpoint URL returned a non-2xx HTTP status. The SSE stream is up and the endpoint URL was re-validated against SSRF rules, but the server rejected the message POST itself (expired session, auth, or upstream error). The pending RPC deferred is rejected with this error and the timeout timer is cleared.

Solutions

  1. Inspect the status in the message: 404 commonly means the session/endpoint expired — reconnect to get a fresh endpoint event
  2. Ensure auth headers are applied to the POST as well as the SSE stream
  3. Retry the whole SSE session (connect + send) for transient 5xx failures
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at api/mcp-proxy.ts:482 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at api/mcp-proxy.ts:485

// name-shaped trampoline that cannot match the spelling it has not seen.
const CROSS_ORIGIN_SAFE_HEADERS = new Set(['content-type', 'accept', 'user-agent']);

function redirectTargetFor(response, fromUrl) {
  const location = response.headers.get('location');
  if (!location) return null;
  let next;
  try {
    next = new URL(location, fromUrl);
  } catch {
    return null;
  }
  // assertServerUrlSafe vets the host but not the scheme, and the entry-point
  // https check in validateServerUrl never sees a redirect target — so a
  // downgrade to http:// has to be refused right here.
  if (next.protocol !== 'https:') return null;
  return next;
}

function stripToCrossOriginSafeHeaders(headers) {
  const out = {};
  for (const [key, value] of Object.entries(headers)) {
    if (CROSS_ORIGIN_SAFE_HEADERS.has(key.toLowerCase())) out[key] = value;
  }
  return out;
}

async function postJson(url, body, headers, sessionId) {
  const h = { ...headers };
  if (sessionId) h['Mcp-Session-Id'] = sessionId;
  const payload = JSON.stringify(body);
  let target = url;
  let outboundHeaders = h;
  // ONE deadline for the whole exchange, not one per hop — a per-hop signal
  // would quietly hand a redirecting upstream twice the budget every other
  // dispatch gets.
  const signal = AbortSignal.timeout(TIMEOUT_MS);

View on GitHub (pinned to e586b8b4b8)