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
- Rename each duplicate listed in the message so every server name is unique
- Delete the accidental clone row if it was a copy-paste leftover
- 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
- Flag duplicate names inline as the user types, per row
- After cloning a server row, auto-suffix the name (e.g. 'github (2)') and force a rename before enable
- Trim names on blur so whitespace-only differences cannot hide duplicates
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
- ${label} must be a JSON object.
- ${label}.${key} must be a string.
- MCP discovery requires at least one search method (BM25 or r
- MCP server ${server.name} requires a URL.
- MCP server ${server.name} requires a valid HTTP(S) URL.
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/8dee75ce704660ba.
Report an issue: GitHub.