nexu-io/open-design · error

brand not found: ${id}

Error message

brand not found: ${id}

What it means

Thrown by finalizeBrand when readMeta(brandsRoot, id) returns null. readMeta reads the brand's meta.json specifically; absence means the brand id does not exist on disk. Different reader than error 31 (readBrandDetail) but the same root cause.

Source

Thrown at apps/daemon/src/brands/index.ts:1333

   *  fallback that runs when the agent captured too few `imagery.samples`. */
  imageryFallback?: ImageryFallbackFn;
  /** Optional override; defaults to the locale stored in brand meta. */
  locale?: string;
}

/**
 * Finalize an agent-extracted brand: read `brand.json` (+ optional BRAND.md,
 * logos, fonts) the agent wrote into the backing project, validate it, derive
 * the deterministic brand-system artifacts, and register the `user:<id>`
 * design system. Marks the brand `ready`. Throws with a precise message when
 * the agent output is missing or invalid.
 */
export async function finalizeBrand(
  opts: FinalizeBrandOptions,
): Promise<BrandFinalizeResponse> {
  const { id, brandsRoot, projectsRoot } = opts;
  const meta = readMeta(brandsRoot, id);
  if (!meta) throw new Error(`brand not found: ${id}`);
  const projectId = opts.projectId ?? meta.projectId ?? brandProjectId(id);

  const brandJsonRaw = await readProjectTextOrNull(projectsRoot, projectId, 'brand.json');
  if (brandJsonRaw === null) {
    throw new Error(
      'brand.json not found in the extraction project — the agent has not written the design system yet.',
    );
  }
  let parsed: unknown;
  try {
    parsed = JSON.parse(brandJsonRaw);
  } catch {
    const block = extractJsonBlock(brandJsonRaw);
    if (block === null) throw new Error('brand.json is not valid JSON.');
    parsed = block;
  }
  let brand: Brand;
  try {

View on GitHub (pinned to 5be4028344)

Solutions

  1. Confirm the brand id via the list endpoint before finalizing.
  2. If the brand was deleted, re-create it with startBrandExtraction and finalize that one.
  3. Check that the daemon is pointing at the same brandsRoot where the brand was created.
Defensive patterns

Strategy: validation

Validate before calling

const meta = readMeta(brandsRoot, id);
if (!meta) throw new NotFoundError(`No brand with id '${id}'. Cannot finalize.`);

Type guard

function hasBrandMeta(meta: unknown): meta is BrandMeta {
  return meta !== null && meta !== undefined && typeof (meta as any).id === 'string';
}

Try / catch

try {
  await finalizeBrand(opts);
} catch (err) {
  if (err instanceof Error && /^brand not found:/.test(err.message)) {
    return notFound('That brand no longer exists; nothing to finalize.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Finalizing a brand id that was deleted, never created, or mistyped; finalizing after the data dir was reset.

Common situations: User clicks Finalize on a stale card after the brand was removed; automation firing finalize against an old id; typo in scripted call.

Related errors


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