sipeed/picoclaw · warning

MCP server names must be unique. Duplicates: ${duplicateName

Error message

MCP server names must be unique. Duplicates: ${duplicateNames.join(", ")}.

What it means

Validation error thrown in handleSave (web/frontend/src/components/config/config-page.tsx:439) when two or more MCP server entries share the same trimmed name. Server names are the keys of the mcpServers patch object, so duplicates would silently overwrite each other; the code builds a name-count map, sorts the duplicate names, and lists them in the message before aborting the save.

Source

Thrown at web/frontend/src/components/config/config-page.tsx:439

              envFile: server.envFile.trim(),
            }))
            .filter((server) => server.name !== "")

          const serverNameCounts = new Map<string, number>()
          for (const server of normalizedServers) {
            serverNameCounts.set(
              server.name,
              (serverNameCounts.get(server.name) ?? 0) + 1,
            )
          }

          const duplicateNames = Array.from(serverNameCounts.entries())
            .filter(([, count]) => count > 1)
            .map(([name]) => name)
            .sort((a, b) => a.localeCompare(b))

          if (duplicateNames.length > 0) {
            throw new Error(
              `MCP server names must be unique. Duplicates: ${duplicateNames.join(", ")}.`,
            )
          }

          const currentServerNames = new Set(
            normalizedServers.map((server) => server.name),
          )

          const removedServerEntries = Array.from(baselineServerNames)
            .filter((name) => !currentServerNames.has(name))
            .map((name) => [name, null] as const)

          const baselineServersByName = new Map(
            baseline.mcpServers
              .map((server) => ({
                ...server,
                name: server.name.trim(),
              }))

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Rename each duplicate listed in the message so every server name is unique
  2. Delete the accidental clone row if it was a copy-paste leftover
  3. Check for invisible leading/trailing spaces — names are trimmed before comparison
Defensive patterns

Strategy: validation

Validate before calling

function findDuplicateServerNames(servers: { name: string }[]): string[] {
  const counts = new Map<string, number>()
  for (const s of servers) {
    const n = s.name.trim()
    if (n === "") continue
    counts.set(n, (counts.get(n) ?? 0) + 1)
  }
  return [...counts.entries()].filter(([, c]) => c > 1).map(([n]) => n)
}

// call before building the patch
const dups = findDuplicateServerNames(form.mcpServers)
if (dups.length > 0) {
  setFieldError(`MCP server names must be unique. Duplicates: ${dups.join(", ")}.`)
  return
}

Try / catch

try {
  await handleSave()
} catch (err) {
  if (err instanceof Error) setError(err.message) // message lists the duplicate names
}

Prevention

When it happens

Trigger: Adding a second server row and typing a name identical (after trimming) to an existing one; a saved config already containing duplicate names that surfaces on the next edit; names differing only by surrounding spaces normalize to the same trimmed value.

Common situations: User clones a server row to tweak a URL and forgets to rename; two people merge config edits introducing the same name 'github'; whitespace differences make names look distinct in the UI.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/8dee75ce704660ba. Report an issue: GitHub.