Skip to content

fix(ai): fall back to default gateway when swarm Bifrost is unreachable#4571

Open
Evanfeenstra wants to merge 1 commit into
masterfrom
fix/llm-gateway-fallback-on-swarm-unreachable
Open

fix(ai): fall back to default gateway when swarm Bifrost is unreachable#4571
Evanfeenstra wants to merge 1 commit into
masterfrom
fix/llm-gateway-fallback-on-swarm-unreachable

Conversation

@Evanfeenstra

Copy link
Copy Markdown
Contributor

Problem

When a workspace's swarm has an expired TLS cert (or is otherwise unreachable), the entire chat turn dies with CERT_HAS_EXPIRED:

[runCanvasAgent] streamText error: Failed after 3 attempts.
  Last error: Cannot connect to API: certificate has expired
  url: 'https://swarm38.sphinx.chat:8181/anthropic/v1/messages'

The LLM inference call routes through one gateway — the primary workspace's swarm Bifrost proxy (bifrost.baseUrl). If that swarm is down, there's no fallback, so the turn fails even when the default gateway is perfectly healthy. (The concept pre-fetch already skips dead swarms; the LLM call didn't.)

Fix

Pre-flight the swarm Bifrost gateway before committing to it:

  • Reachable (any resolved HTTP response, even 404/401 → TLS+TCP handshake OK): keep the swarm route.
  • Unreachable (CERT_HAS_EXPIRED, ECONNREFUSED, timeout, fetch failed): drop the entire Bifrost bundle (baseUrl + VK + macaroon) and fall back to the plain default gateway — the same path a non-Bifrost workspace already uses (default key, no override).

We probe instead of catching a mid-stream streamText error because by the time that surfaces, the 200 + SSE response is already returned to the client and the stream can't be restarted.

This is not disabling cert verification — it routes around the broken swarm. The swarm cert still needs renewing; this just stops it from taking down chat.

Changes

  • src/lib/ai/provider.ts — shared isGatewayReachable(baseUrl) probe (3s timeout).
  • src/lib/ai/runCanvasAgent.ts — main canvas stream falls back to the default gateway when the swarm gateway is unreachable (covers /api/ask/quick and /api/ask/sync). Adds a bifrostFellBack flag to the streamText log.
  • src/services/canvas-turn-enrichments.ts — follow-up-questions generateObject (which failed the same way) gets the same fallback.

Verification

Probed the real endpoint https://swarm38.sphinx.chat:8181:

  • Node fetch to root resolves HTTP 200isGatewayReachable() returns true → no false fallbacks on a healthy gateway; no need for a special /health path.
  • When the cert is expired, Node fetch rejects → probe returns false → fall back to default gateway.

Tradeoffs

  • Adds one cheap probe round-trip per Bifrost-routed turn (only for workspaces in the BIFROST_ENABLED allow-list). ~50–200ms on a healthy swarm; fails fast and rescues the turn on a dead one.
  • Only falls back on connectivity/TLS failures. If the gateway connects but the upstream model 500s, we keep the swarm route and surface the real error.

The LLM inference call routes through one gateway — the primary
workspace's swarm Bifrost proxy. When that swarm is unreachable (expired
TLS cert, connection refused, timeout) the whole chat turn died with
CERT_HAS_EXPIRED, even when the default gateway was healthy.

Pre-flight the swarm gateway before committing to it: any resolved HTTP
response means the connection is fine (keep the swarm route); a rejection
means drop the entire Bifrost bundle (baseUrl + VK + macaroon) and fall
back to the plain default gateway — the same path a non-Bifrost workspace
takes. We probe rather than catch a mid-stream streamText error because by
then the SSE response is already returned and the stream can't restart.

Applied to both the main canvas stream (runCanvasAgent) and the follow-up
questions enrichment. Verified against swarm38: a healthy gateway returns
200 at root, so no false fallbacks.
@github-actions

Copy link
Copy Markdown

Test environment is now live.

View it at: https://hive-preview-2.sphinx.chat

Database expires at: Jun 28, 2026, 5:41 AM UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant