nexu-io/open-design · warning · Error

no project matches

Error message

no project matches "${arg}"

What it means

Thrown by resolveProjectId when the supplied name/fragment matches no project via exact, slug, or substring comparison. This is the classic typo / stale-reference error.

Solutions

  1. List projects via the project MCP tool and copy the exact name or UUID.
  2. Check for typos, trailing spaces, and case differences (comparison is case-insensitive but exact match must equal).
  3. Confirm the daemon/OD_DATA_DIR/namespace is the one holding the project.
  4. If the project was renamed, update the reference to the new name or its UUID.

Example fix

// before
runStart({ project: "mydeck" })  // real name is "my-deck"
// after
runStart({ project: "my-deck" })
Defensive patterns

Strategy: validation

Validate before calling

const exists = list.some(p => p.id === project || p.name.toLowerCase() === project.toLowerCase());
if (!exists) throw new Error(`project "${project}" not found; available: ${list.map(p => p.name).join(', ')}`);

Prevention

When it happens

Trigger: Typo in project name; referencing a project that was deleted or renamed; pointing at the wrong daemon/data root where the project does not exist; copy-paste of a name with extra whitespace or hidden characters.

Common situations: Renamed projects breaking hardcoded references; env drift between dev/staging daemons; trailing whitespace in the arg; the project lives under a different namespace.

Related errors


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

Appendix: source

Thrown at apps/daemon/src/mcp.ts:3000

  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,
  relPath: string,
  active: ActiveContext | null,
  resolved?: ResolvedProject | null,
  offset = 0,

View on GitHub (pinned to 5be4028344)