can1357/oh-my-pi · error · Error

nameError (dynamic message from validateServerName, e.g. "Se

Error message

nameError (dynamic message from validateServerName, e.g. "Server name cannot be empty")

What it means

addMCPServer validates the requested server name via validateServerName before writing config; a failing name (empty, >100 chars, or containing characters outside [a-zA-Z0-9_.:-]) becomes the thrown Error message directly (e.g. 'Server name cannot be empty', 'Server name is too long (max 100 characters)', 'Server name can only contain letters, numbers, dash, underscore, dot, and colon').

Source

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

	// sanitize them via createMCPToolName) and `/mcp reauth` writes such names back
	// as a user-config override that shadows the discovered entry.
	if (!/^[a-zA-Z0-9_.:-]+$/.test(name)) {
		return "Server name can only contain letters, numbers, dash, underscore, dot, and colon";
	}
	return undefined;
}

/**
 * Add an MCP server to a config file.
 * Validates the config before writing.
 *
 * @throws Error if server name already exists or validation fails
 */
export async function addMCPServer(filePath: string, name: string, config: MCPServerConfig): Promise<void> {
	// Validate server name
	const nameError = validateServerName(name);
	if (nameError) {
		throw new Error(nameError);
	}

	// Validate the config
	const errors = validateServerConfig(name, config);
	if (errors.length > 0) {
		throw new Error(`Invalid server config: ${errors.join("; ")}`);
	}

	// Serialize the read-modify-write under a per-file lock so a concurrent
	// mutation cannot overwrite this one (lost update). The lock also guards
	// against cross-process writers sharing the same config file.
	await withConfigLock(filePath, async () => {
		const existing = await readMCPConfigFile(filePath);

		// Check for duplicate name
		if (existing.mcpServers?.[name]) {
			throw new Error(`Server "${name}" already exists in ${filePath}`);
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Provide a non-empty name using only letters, numbers, dash, underscore, dot, and colon.
  2. Shorten the name to ≤100 characters.
  3. Sanitize the name in the calling wizard/command before invoking addMCPServer (call validateServerName yourself for early feedback).
  4. Use a short id like 'my-server-1' rather than a label or path.

Example fix

// before
await addMCPServer(path, "My MCP Server / v2", config);
// after
await addMCPServer(path, "my-mcp-server-v2", config);
Defensive patterns

Strategy: validation

Validate before calling

import { validateServerName } from "./config-writer";
function assertValidName(name: string): void {
  const err = validateServerName(name);
  if (err) throw new Error(`Pre-check: ${err}`);
}

Type guard

function isValidServerName(name: string): boolean {
  return name.length > 0 && name.length <= 100 && /^[a-zA-Z0-9_.:-]+$/.test(name);
}

Try / catch

try {
  await addMCPServer(path, name, config);
} catch (err) {
  if (err instanceof Error && /^(Server name cannot be empty|Server name is too long|Server name can only contain)/.test(err.message)) {
    console.error(`${err.message}; pick a short id like 'my-server-1'`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling addMCPServer(filePath, name, config) — directly or via #handleWizardComplete / handleAddCommand — with an empty name, a name over 100 characters, or one containing spaces/slashes/unicode outside the allowed set.

Common situations: Wizard submitted with a blank name field; server name copied from a URL containing '/' or '?'; names with spaces from display labels; pasting a fully-qualified command path as the server name.

Related errors


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