chatboxai/chatbox · error · Error
Streamable HTTP connection failed: ${streamableMessage}\nLeg
Error message
Streamable HTTP connection failed: ${streamableMessage}\nLegacy SSE fallback failed: ${fallbackMessage} What it means
Thrown by createClient() in the MCP controller when an HTTP-type transport fails to connect via the modern StreamableHTTPClientTransport AND the legacy SSE fallback also fails. The combined message embeds both underlying error messages and chains the original streamable error as `cause`, so both failure modes are visible in one error.
Source
Thrown at src/renderer/packages/mcp/controller.ts:63
})
} catch (err) {
console.error('Streamable HTTP connection failed', err)
try {
return await createMCPClient({
name,
transport: {
type: 'sse',
url: transportConfig.url,
headers: transportConfig.headers,
},
onUncaughtError(error: unknown) {
console.error('mcp:client:onUncaughtError', error)
},
})
} catch (fallbackError) {
const streamableMessage = err instanceof Error ? err.message : String(err)
const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError)
throw new Error(
`Streamable HTTP connection failed: ${streamableMessage}\nLegacy SSE fallback failed: ${fallbackMessage}`,
{ cause: err }
)
}
}
}
throw new Error('Unknown transport type')
}
export class MCPServer extends Emittery<{ status: MCPServerStatus }> {
private _status: MCPServerStatus = { state: 'idle' }
private client?: MCPClient
private tools?: ToolSet
constructor(private readonly transportConfig: TransportConfig) {
super()
}
View on GitHub (pinned to 81571269ad)
Solutions
- Read both embedded messages: the streamable message usually identifies the primary failure (auth, 404, DNS) — fix that first.
- Verify the server URL is correct, reachable, and serves the MCP streamable-HTTP or SSE endpoint.
- Check transportConfig.headers for missing/invalid auth tokens.
- If the server only supports SSE, consider configuring transport.type 'sse' directly to get a cleaner single error.
- Confirm network/CORS allows the renderer to reach the endpoint.
Defensive patterns
Strategy: retry
Validate before calling
function isValidHttpTransportConfig(c: TransportConfig): boolean {
return c.type === 'http' && typeof c.url === 'string' && URL.canParse(c.url)
}
// pre-check connectivity before createClient:
// await fetch(url, { method: 'HEAD' }).catch(() => null) as a cheap liveness probe Type guard
function isHttpTransportConfig(c: TransportConfig): c is { type: 'http'; url: string; headers?: Record<string,string> } {
return c.type === 'http'
} Try / catch
try {
await createClient(transportConfig)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Streamable HTTP connection failed')) {
// inspect e.cause and e.message; offer to switch transport.type or check URL/headers
}
throw e
} Prevention
- Validate the server URL and headers before connecting.
- Keep transport.type 'http' to benefit from the SSE fallback rather than forcing one protocol.
- Surface both embedded messages to the user for diagnosis.
When it happens
Trigger: An MCP server config with transport.type 'http' whose URL is unreachable or returns errors for BOTH the streamable-HTTP handshake and the SSE fallback path. This is the catch block reached only after both createMCPClient attempts inside the 'http' branch throw.
Common situations: Wrong/unreachable server URL; server requires auth headers that are missing or wrong; CORS/network policy blocks both transport protocols; server only speaks an older MCP protocol unsupported by both transports; the server is down.
Related errors
- Failed to start server: ${server.status.state}
- Unknown transport type
- Knowledge base name cannot be empty
- Token exchange failed: ${error}
- Token refresh failed: ${error}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/bf20cf79ee82a89d.
Report an issue: GitHub.