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

  1. Pass the full UUID of the intended project as listed in the error message.
  2. Use the exact full project name (case-insensitive) so the exact-match branch wins.
  3. Rename projects to remove ambiguity, or archive duplicates.
  4. 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

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


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/363dbb0105c815e3. Report an issue: GitHub.