ruvnet/ruflo · error · Error

Failed to fetch base servers: ${response.statusText}

Error message

Failed to fetch base servers: ${response.statusText}

What it means

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.

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 default

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Open ${base}/api/mcp/servers in a browser/devtools and read the actual status + body.
  2. Confirm the SvelteKit server is running and the backend route exists under src/routes/api/mcp/servers.
  3. Check server logs for the 500 that produced the statusText.
  4. Verify auth/session cookies if the endpoint requires a logged-in user.
  5. Wrap the call site in a retry with backoff for transient 5xx, and degrade to customServers + wasmServer only on persistent failure.

Example fix

// before
const response = await fetch(`${base}/api/mcp/servers`);
if (!response.ok) throw new Error(`Failed to fetch base servers: ${response.statusText}`);
// after
const response = await fetch(`${base}/api/mcp/servers`);
if (!response.ok) {
  const body = await response.text().catch(() => "");
  throw new Error(`Failed to fetch base servers: ${response.status} ${response.statusText} ${body}`);
}
Defensive patterns

Strategy: retry

Validate before calling

async function pingMcpServers(base: string, fetchFn = fetch): Promise<boolean> {
  try {
    const r = await fetchFn(`${base}/api/mcp/servers`, { method: "GET" });
    return r.ok;
  } catch {
    return false;
  }
}
// before refreshMcpServers:
if (!(await pingMcpServers(base))) {
  console.warn("backend /api/mcp/servers unreachable; skipping base server refresh");
}

Type guard

function isMCPServerArray(x: unknown): x is MCPServer[] {
  return Array.isArray(x) && x.every((s) => s && typeof s.id === "string" && typeof s.name === "string");
}

Try / catch

async function refreshMcpServersSafe() {
  try {
    await refreshMcpServers();
  } catch (e) {
    console.warn("base MCP servers unavailable, continuing with custom+WASM only:", String((e as Error)?.message ?? e));
    allMcpServers.set([createWasmServer(), ...loadCustomServers()]);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/f148691bf8d189af. Report an issue: GitHub.