can1357/oh-my-pi · error · MCPTransportError

HTTP ${response.status}: ${text}${suffix}

Error message

HTTP ${response.status}: ${text}${suffix}

What it means

The MCP JSON-RPC POST received a non-2xx HTTP status. The transport reads the response body and any auth hint headers (WWW-Authenticate, Mcp-Auth-Server), appends them in brackets, and throws an MCPTransportError with failure: http_status and the status as code. Only 404/502/503 are marked retryable.

Source

Thrown at packages/coding-agent/src/mcp/transports/http.ts:481

			// Check for session ID in response
			const newSessionId = response.headers.get("Mcp-Session-Id");
			if (newSessionId) {
				this.#sessionId = newSessionId;
			}

			if (!response.ok) {
				const text = await response.text();
				const wwwAuthenticate = response.headers.get("WWW-Authenticate");
				const mcpAuthServer = response.headers.get("Mcp-Auth-Server");
				const authHints = [
					wwwAuthenticate ? `WWW-Authenticate: ${wwwAuthenticate}` : null,
					mcpAuthServer ? `Mcp-Auth-Server: ${mcpAuthServer}` : null,
				]
					.filter(Boolean)
					.join("; ");
				const suffix = authHints ? ` [${authHints}]` : "";
				throw new MCPTransportError({
					transport: "http",
					stage,
					failure: "http_status",
					message: `HTTP ${response.status}: ${text}${suffix}`,
					retryable: response.status === 404 || response.status === 502 || response.status === 503,
					code: response.status,
					traceId,
				});
			}

			const contentType = response.headers.get("Content-Type") ?? "";

			// Handle SSE response
			if (contentType.includes("text/event-stream")) {
				return this.#parseSSEResponse<T>(response, id, options);
			}

			stage = "decode";

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the status and bracketed auth hints: 401/403 → fix credentials or wire onAuthError for automatic refresh; 404 → verify URL and reconnect for a new session; 429 → back off; 5xx → check server health
  2. Retry if status is 404/502/503 (marked retryable), otherwise correct the underlying cause first
  3. Confirm the MCP endpoint URL matches the server's advertised path and protocol version
  4. Inspect traceId against server logs to correlate the rejected request

Example fix

// before
await transport.request("tools/list"); // throws HTTP 404 after server restart evicted session
// after
await transport.connect(); // re-establish session, gets fresh Mcp-Session-Id
await transport.request("tools/list");
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the endpoint and credentials:
const res = await fetch(url, { method: "OPTIONS" });
if (res.status === 401 || res.status === 403) throw new Error("credentials invalid before any request");

Try / catch

try {
  await transport.request(method, params);
} catch (err) {
  if (err instanceof MCPTransportError && err.failure === "http_status") {
    if (err.code === 401 || err.code === 403) await refreshAuth();
    else if (err.retryable) await backoffAndRetry();
    else throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: Server responds 4xx/5xx to a JSON-RPC POST: 401/403 (auth rejected), 404 (wrong URL or evicted session), 429 (rate limit), 5xx (server fault); auth hints included when the server supplies WWW-Authenticate or Mcp-Auth-Server.

Common situations: Expired/invalid API keys; hitting the wrong endpoint path; Mcp-Session-Id expired after server restart; server overloaded or down; rate limiting from aggressive polling.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4eccdb3a3fb16fee. Report an issue: GitHub.