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

  1. Read both embedded messages: the streamable message usually identifies the primary failure (auth, 404, DNS) — fix that first.
  2. Verify the server URL is correct, reachable, and serves the MCP streamable-HTTP or SSE endpoint.
  3. Check transportConfig.headers for missing/invalid auth tokens.
  4. If the server only supports SSE, consider configuring transport.type 'sse' directly to get a cleaner single error.
  5. 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

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


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/bf20cf79ee82a89d. Report an issue: GitHub.