ruvnet/ruflo · error
HTTP transport failed: ${firstError instanceof Error ? first
Error message
HTTP transport failed: ${firstError instanceof Error ? firstError.message : firstError}; SSE fallback failed: ${err instanceof Error ? err.message : err} What it means
The combined failure of last resort in getClient(): Streamable HTTP failed recoverably (network-level or 408, i.e. not a definitive HTTP status) and the SSE fallback also failed without a definitive status. The message concatenates both transport errors (clientPool.ts:208) and attaches the SSE error as cause — meaning the server was never reached successfully over either transport.
Source
Thrown at ruflo/src/ruvocal/src/lib/server/mcp/clientPool.ts:208
recordFailure(key, 429, err);
throw new McpRateLimitedError(
server.name,
429,
retryAfterMs,
err instanceof Error ? err.message : String(err)
);
}
if (effectiveStatus !== undefined) {
recordFailure(key, effectiveStatus, err);
}
const message =
"HTTP transport failed: " +
String(firstError instanceof Error ? firstError.message : firstError) +
"; SSE fallback failed: " +
String(err instanceof Error ? err.message : err);
throw new Error(message, { cause: err instanceof Error ? err : undefined });
}
}
pool.set(key, client);
return client;
}
export async function drainPool() {
for (const [key, client] of pool) {
try {
await client.close?.();
} catch {}
pool.delete(key);
}
failureCooldown.clear();
}
export function evictFromPool(server: McpServerConfig): Client | undefined {View on GitHub (pinned to fa13ee4ad6)
Solutions
- Read both halves of the message plus err.cause — the first names the HTTP transport error, the second the SSE error
- Verify reachability from the same host: curl -v https://<host>/mcp (and /sse), check DNS and TLS
- Fix the URL/port in MCP_SERVERS; for TLS issues add the CA to NODE_EXTRA_CA_CERTS or fix the cert
- If the server is stdio-only, front it with an HTTP/SSE gateway (e.g. mcp-proxy) before configuring it here
- Retry with backoff for genuinely transient network blips
Example fix
// before
const client = await getClient(server); // HTTP transport failed: fetch failed; SSE fallback failed: ...
// after (surface actionable detail + retry transient failures once)
try {
client = await getClient(server);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|certificate/i.test(msg)) {
throw error(502, `MCP server unreachable — check MCP_SERVERS url/TLS: ${msg}`);
}
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
async function mcpReachable(url: string): Promise<boolean> {
try {
const u = new URL(url);
await new Promise((r) => setTimeout(r, 0));
await fetch(u.origin, { method: "HEAD" });
return true;
} catch {
return false;
}
} Type guard
function isMcpDualTransportError(e: unknown): boolean {
return (
e instanceof Error &&
e.message.startsWith("HTTP transport failed:") &&
e.message.includes("SSE fallback failed:")
);
} Try / catch
try {
client = await getClient(server);
} catch (e) {
if (isMcpDualTransportError(e)) {
// transient network class: bounded backoff, then surface 502 with both causes
throw error(502, `MCP server unreachable: ${e.message}`);
}
throw e;
} Prevention
- Pre-flight MCP_SERVERS URLs (DNS + TLS) from the deployment network, not just your laptop
- For stdio-only MCP servers, front them with an HTTP gateway before configuring them here
- Include err.cause in logs — the SSE half usually names the real network error
When it happens
Trigger: DNS resolution failure, connection refused, TLS certificate error, firewall/egress block, or a server supporting neither streamable HTTP nor SSE — e.g. wrong host/port in MCP_SERVERS, self-signed cert rejected by Node, or a proxy that terminates both /mcp and /sse requests.
Common situations: Typo'd hostname or port; corporate egress proxy blocking outbound MCP traffic; cert chain not trusted in the container; the MCP server only speaks stdio (not supported by this remote-client pool); IPv6-only upstream unreachable from the host.
Related errors
- PRIVATE_ADDRESS
- Stdio transport already running
- network
- HTTP transport already running
- HTTP transport requires host and port configuration
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/b2956df200c4c10b.
Report an issue: GitHub.