nexu-io/open-design · warning · Error
multiple projects match "${arg}": ${opts}. Pass the UUID ins
Error message
multiple projects match "${arg}": ${opts}. Pass the UUID instead. What it means
Thrown by resolveProjectId when more than one project's name contains the supplied substring and no exact/slug/unique match won. The resolver tries exact name, normalized slug, then substring fallback; if substring yields >1 it refuses to guess. The message lists each candidate as `name (id)`.
Source
Thrown at apps/daemon/src/mcp.ts:2996
.replace(/[\s_-]+/g, '-');
const target = norm(arg);
const idMatch = list.find((p) => p.id === arg);
if (idMatch) return { id: idMatch.id, name: idMatch.name, source: 'id' as const };
const exact = list.filter((p) => String(p.name || '').toLowerCase() === lower);
if (exact.length === 1) { const p = exact[0]!; return { id: p.id, name: p.name, source: 'exact' as const }; }
const slugged = list.filter((p) => norm(p.name) === target);
if (slugged.length === 1) { const p = slugged[0]!; return { id: p.id, name: p.name, source: 'slug' as const }; }
const subs = list.filter((p) =>
String(p.name || '').toLowerCase().includes(lower),
);
if (subs.length === 1) { const p = subs[0]!; return { id: p.id, name: p.name, source: 'substring' as const }; }
if (subs.length > 1) {
const opts = subs.map((p) => `${p.name} (${p.id})`).join(', ');
throw new Error(
`multiple projects match "${arg}": ${opts}. Pass the UUID instead.`,
);
}
throw new Error(`no project matches "${arg}"`);
}
async function getJson<T>(url: string, headers?: Record<string, string>): Promise<T> {
const resp = await fetch(url, headers ? { headers } : undefined);
if (!resp.ok) {
const body = await safeText(resp);
throw new Error(`daemon ${resp.status} on ${url}: ${body || resp.statusText}`);
}
return (await resp.json()) as T;
}
async function getFile(
baseUrl: string,
project: string,View on GitHub (pinned to 5be4028344)
Solutions
- Pass the full UUID of the intended project as listed in the error message.
- Use the exact full project name (case-insensitive) so the exact-match branch wins.
- Rename projects to remove ambiguity, or archive duplicates.
- List projects first to confirm names/ids before resolving.
Example fix
// before
runStart({ project: "test" }) // matches test-1 and test-2
// after
runStart({ project: "9f3c1a2e-...-uuid" }) // full UUID from the error Defensive patterns
Strategy: validation
Validate before calling
const matches = list.filter(p => p.name.toLowerCase().includes(q.toLowerCase()));
if (matches.length > 1) throw new Error(`ambiguous; pass UUID: ${matches.map(m => m.id).join(', ')}`); Prevention
- Always resolve with the full UUID when names may collide.
- Use exact full names rather than substrings.
- Rename or archive projects with confusingly similar names.
When it happens
Trigger: Passing a short or common fragment like `project: "test"` when `test-1`, `test-2`, and `latest-test` all exist; passing a partial UUID prefix that matches several.
Common situations: Multiple similarly-named projects accumulated over time; template-generated names sharing a prefix; passing a team or category substring instead of a specific project name.
Related errors
- project arg omitted and active context lookup failed: ${erro
- project arg omitted and Open Design has no active project. T
- project is required (string).
- no projects on this daemon
- no project matches "${arg}"
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/363dbb0105c815e3.
Report an issue: GitHub.