ruvnet/ruflo · error
Failed to fetch base servers
Error message
Failed to fetch base servers: ${response.statusText} What it means
Thrown inside refreshMcpServers(), the client-side Svelte store that merges MCP servers from the app's own API (${base}/api/mcp/servers) with locally-stored custom servers and the WASM server. A non-OK HTTP status aborts the refresh; the surrounding try/catch records the error in store state, so the user sees a stale or empty server list.
Solutions
- Reproduce in the browser: open ${base}/api/mcp/servers directly and read the status/body.
- 401/403: re-login or refresh the session; verify MCP_FORWARD_HF_USER_TOKEN and the user's HF token if server-side overlay auth is enabled.
- 500: check server logs for the MCP hub error (often the upstream MCP host or MCP_SERVERS env parse).
- 404/misroute: fix the reverse proxy so /api/mcp/servers reaches the SvelteKit server unchanged.
- Reload the page after fixing — refreshMcpServers is called on init and will repopulate the store.
Defensive patterns
Strategy: try-catch
Validate before calling
// probe before relying on the store
const res = await fetch(`${base}/api/mcp/servers`);
if (!res.ok) {
throw new Error(`MCP servers endpoint returned ${res.status}`);
} Try / catch
try {
await refreshMcpServers();
} catch (err) {
// store keeps previous allMcpServers value; surface error state to the UI
console.error("mcp refresh failed", err);
} Prevention
- Keep the store's previous value on failure so the UI degrades to the last good list.
- Show the HTTP status from the network tab when debugging; it distinguishes auth vs server vs routing.
- Ensure reverse proxies forward /api/mcp/* and session cookies unchanged.
When it happens
Trigger: Browser fetch to /api/mcp/servers returns non-2xx: 401/403 when the session expired or MCP_FORWARD_HF_USER_TOKEN forwarding rejected the token; 500 when server-side MCP hub configuration (MCP_SERVERS) is broken; 404 after a route change or bad `base` in a reverse-proxy deployment.
Common situations: Logged-out or expired-cookie tab refreshing MCP servers; reverse proxy stripping or misrouting /api/mcp/*; server-side MCP hub (Hugging Face MCP host) outage; deploying front and back on different origins without forwarding the path.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- FORBIDDEN_HEADER
- FORBIDDEN_PROTOCOL
- HTTP transport already running
- HTTP transport requires host and port configuration
- INVALID_HEADER_VALUE
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/f148691bf8d189af.
Report an issue: GitHub.
Appendix: source
Thrown at ruflo/src/ruvocal/src/lib/stores/mcpServers.ts:171
export const allBaseServersEnabled = derived(
[allMcpServers, selectedServerIds],
([$all, $selected]) => {
const baseServers = $all.filter((s) => s.type === "base");
return baseServers.length > 0 && baseServers.every((s) => $selected.has(s.id));
}
);
// Note: Authorization overlay (with user's HF token) for the Hugging Face MCP host
// is applied server-side when enabled via MCP_FORWARD_HF_USER_TOKEN.
/**
* Refresh base servers from API and merge with custom servers + WASM server
*/
export async function refreshMcpServers() {
try {
const response = await fetch(`${base}/api/mcp/servers`);
if (!response.ok) {
throw new Error(`Failed to fetch base servers: ${response.statusText}`);
}
const baseServers: MCPServer[] = await response.json();
const customServers = loadCustomServers();
// Create WASM server and add to the list
const wasmServer = createWasmServer();
// Merge base, custom, and WASM servers
const merged = [wasmServer, ...baseServers, ...customServers];
allMcpServers.set(merged);
// Load disabled base servers
const disabledBaseIds = loadDisabledBaseIds();
// Auto-enable all base servers that aren't explicitly disabled
// Plus keep any custom servers that were previously selected
// WASM server is auto-enabled by defaultView on GitHub (pinned to fa13ee4ad6)