can1357/oh-my-pi · error · Error

Server "${name}" not found in ${filePath}

Error message

Server "${name}" not found in ${filePath}

What it means

removeMCPServer() throws when the named server does not exist in the target config file. Inside the config lock it reads the config and throws if existing.mcpServers[name] is absent, so callers get a clear message naming both the server and the file instead of a silent no-op.

Source

Thrown at packages/coding-agent/src/mcp/config-writer.ts:190

				[name]: config,
			},
		};
		await writeMCPConfigFile(filePath, updated);
	});
}

/**
 * Remove an MCP server from a config file.
 *
 * @throws Error if server doesn't exist
 */
export async function removeMCPServer(filePath: string, name: string): Promise<void> {
	// Serialize the read-modify-write (see addMCPServer).
	await withConfigLock(filePath, async () => {
		const existing = await readMCPConfigFile(filePath);

		if (!existing.mcpServers?.[name]) {
			throw new Error(`Server "${name}" not found in ${filePath}`);
		}

		const { [name]: _removed, ...remaining } = existing.mcpServers;
		const updated: MCPConfigFile = {
			...existing,
			mcpServers: remaining,
		};
		await writeMCPConfigFile(filePath, updated);
	});
}

/**
 * Get a specific server config from a file.
 * Returns undefined if server doesn't exist.
 */
export async function getMCPServer(filePath: string, name: string): Promise<MCPServerConfig | undefined> {
	const config = await readMCPConfigFile(filePath);
	return config.mcpServers?.[name];

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the exact name in the config file at filePath (grep for the name).
  2. Confirm you are editing the file the server is actually defined in (global vs project config).
  3. Trim/copy the name exactly as it appears, including any namespace prefix and colon.
  4. Make cleanup scripts idempotent: check existence before removing and treat absence as success.
  5. If it may not exist, use readMCPConfigFile first: if (!cfg.mcpServers?.[name]) skip the remove call.

Example fix

// before
await removeMCPServer(cfgPath, name); // throws if absent
// after
const cfg = await readMCPConfigFile(cfgPath);
if (cfg.mcpServers?.[name]) {
  await removeMCPServer(cfgPath, name);
}
Defensive patterns

Strategy: validation

Validate before calling

import { readMCPConfigFile } from "@oh-my-pi/pi-coding-agent/mcp/config";
const cfg = await readMCPConfigFile(filePath);
if (!cfg.mcpServers?.[name]) return; // nothing to remove; skip
copyExactNameFromConfig(name);

Type guard

function isKnownServer(cfg: { mcpServers?: Record<string, unknown> }, name: string): boolean {
  return Object.prototype.hasOwnProperty.call(cfg.mcpServers ?? {}, name);
}

Try / catch

try {
  await removeMCPServer(cfgPath, name);
} catch (e) {
  if (e instanceof Error && e.message.includes('not found in')) {
    return; // idempotent delete: already gone
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling removeMCPServer(filePath, name) (or #handleRemove / handleRemoveCommand) when the config file has no mcpServers entry under that exact name — wrong name, wrong file, or the entry lives in a different config source (project vs global config).

Common situations: Server was already removed (double delete or rerun script); name mismatch (case sensitivity, whitespace, missing namespace prefix like "plugin:server"); the server is defined in project .omp/mcp.json but you are editing the global file; config was regenerated and lost the entry.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5695b672841e0b79. Report an issue: GitHub.