{"record":{"id":"f148691bf8d189af","repo":"ruvnet/ruflo","slug":"failed-to-fetch-base-servers-response-statustex","errorCode":null,"errorMessage":"Failed to fetch base servers: ${response.statusText}","messagePattern":"Failed to fetch base servers: (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/stores/mcpServers.ts","lineNumber":171,"sourceCode":"export const allBaseServersEnabled = derived(\n\t[allMcpServers, selectedServerIds],\n\t([$all, $selected]) => {\n\t\tconst baseServers = $all.filter((s) => s.type === \"base\");\n\t\treturn baseServers.length > 0 && baseServers.every((s) => $selected.has(s.id));\n\t}\n);\n\n// Note: Authorization overlay (with user's HF token) for the Hugging Face MCP host\n// is applied server-side when enabled via MCP_FORWARD_HF_USER_TOKEN.\n\n/**\n * Refresh base servers from API and merge with custom servers + WASM server\n */\nexport async function refreshMcpServers() {\n\ttry {\n\t\tconst response = await fetch(`${base}/api/mcp/servers`);\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to fetch base servers: ${response.statusText}`);\n\t\t}\n\n\t\tconst baseServers: MCPServer[] = await response.json();\n\t\tconst customServers = loadCustomServers();\n\n\t\t// Create WASM server and add to the list\n\t\tconst wasmServer = createWasmServer();\n\n\t\t// Merge base, custom, and WASM servers\n\t\tconst merged = [wasmServer, ...baseServers, ...customServers];\n\t\tallMcpServers.set(merged);\n\n\t\t// Load disabled base servers\n\t\tconst disabledBaseIds = loadDisabledBaseIds();\n\n\t\t// Auto-enable all base servers that aren't explicitly disabled\n\t\t// Plus keep any custom servers that were previously selected\n\t\t// WASM server is auto-enabled by default","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/ruflo/src/ruvocal/src/lib/stores/mcpServers.ts#L153-L189","documentation":"Thrown by refreshMcpServers() in the client-side Svelte store when GET ${base}/api/mcp/servers returns a non-OK HTTP status. The store merges base servers with custom servers and the WASM server, so a failed base fetch aborts the whole refresh. The error carries only response.statusText, not the body.","triggerScenarios":"The /api/mcp/servers endpoint returns 4xx/5xx (backend down, auth required, route missing), the dev server is not running, the base path is misconfigured, or a proxy/CORS preflight fails and surfaces as a non-OK response.","commonSituations":"Running only the client without the SvelteKit backend; OPENAI_BASE_URL / app base path wrong; backend crashed during startup so /api/mcp/servers 500s; a deploy where the API mount point changed.","solutions":["Open ${base}/api/mcp/servers in a browser/devtools and read the actual status + body.","Confirm the SvelteKit server is running and the backend route exists under src/routes/api/mcp/servers.","Check server logs for the 500 that produced the statusText.","Verify auth/session cookies if the endpoint requires a logged-in user.","Wrap the call site in a retry with backoff for transient 5xx, and degrade to customServers + wasmServer only on persistent failure."],"exampleFix":"// before\nconst response = await fetch(`${base}/api/mcp/servers`);\nif (!response.ok) throw new Error(`Failed to fetch base servers: ${response.statusText}`);\n// after\nconst response = await fetch(`${base}/api/mcp/servers`);\nif (!response.ok) {\n  const body = await response.text().catch(() => \"\");\n  throw new Error(`Failed to fetch base servers: ${response.status} ${response.statusText} ${body}`);\n}","handlingStrategy":"retry","validationCode":"async function pingMcpServers(base: string, fetchFn = fetch): Promise<boolean> {\n  try {\n    const r = await fetchFn(`${base}/api/mcp/servers`, { method: \"GET\" });\n    return r.ok;\n  } catch {\n    return false;\n  }\n}\n// before refreshMcpServers:\nif (!(await pingMcpServers(base))) {\n  console.warn(\"backend /api/mcp/servers unreachable; skipping base server refresh\");\n}","typeGuard":"function isMCPServerArray(x: unknown): x is MCPServer[] {\n  return Array.isArray(x) && x.every((s) => s && typeof s.id === \"string\" && typeof s.name === \"string\");\n}","tryCatchPattern":"async function refreshMcpServersSafe() {\n  try {\n    await refreshMcpServers();\n  } catch (e) {\n    console.warn(\"base MCP servers unavailable, continuing with custom+WASM only:\", String((e as Error)?.message ?? e));\n    allMcpServers.set([createWasmServer(), ...loadCustomServers()]);\n  }\n}","preventionTips":["Add a health-check call before the first refresh so the UI does not throw on cold start.","Retry 5xx with exponential backoff; do not retry 4xx.","Degrade gracefully: base servers are additive, so the store can still show custom + WASM servers when base is down."],"tags":["network","mcp","fetch","client","store"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}