nexu-io/open-design · error · Error
brand.json not found for brand "${id}"
Error message
brand.json not found for brand "${id}" What it means
Thrown by rebuildSystem when readBrand returns null — the brand dir has no readable brand.json. Distinct from an invalid id: the id passed the regex, but the canonical Brand file is missing or unreadable. rebuildSystem cannot proceed because the entire system is derived from the Brand object.
Source
Thrown at apps/daemon/src/brands/system.ts:130
process.exit(1);
}
const here = path.dirname(fileURLToPath(import.meta.url));
const source = path.resolve(here, '..', 'variables.css');
const destination = path.resolve(process.cwd(), target);
fs.mkdirSync(path.dirname(destination), { recursive: true });
fs.copyFileSync(source, destination);
console.log(\`Copied design tokens to \${destination}\`);
`;
}
export async function rebuildSystem(
brandsRoot: string,
id: string,
seedOverrides?: Partial<SeedToken>,
): Promise<{ themes: string[]; files: string[] }> {
const brand = readBrand(brandsRoot, id) as Brand | null;
if (!brand) throw new Error(`brand.json not found for brand "${id}"`);
if (seedOverrides !== undefined) {
const merged = sanitizeSeedOverrides({ ...brand.seed, ...seedOverrides });
if (merged) brand.seed = merged;
else delete brand.seed;
writeBrand(brandsRoot, id, brand);
}
const overrides = sanitizeSeedOverrides(brand.seed);
const fontFiles = readFontManifest(brandRoot(brandsRoot, id));
let system = buildBrandSystem(brand, { fontFiles });
if (overrides) {
system = reassembleWithSeed(system, brand, { ...system.seed, ...overrides }, fontFiles);
}
// Layout-validation guard: the deck lays content on fixed-size 16:9 slides,
// so a regressed template can clip / truncate / overflow brand copy. Block
// the rebuild before anything is written when the no-clip invariants fail.View on GitHub (pinned to 5be4028344)
Solutions
- Wait for extraction to reach the terminal state (check BrandMeta.extractionTerminalRunId / state) before rebuild.
- If the brand was deleted, surface a 404 to the caller and remove it from any cached list.
- If brand.json is corrupted, re-run extraction rather than reconstructing the file by hand.
- Guard rebuild with readBrand(brandsRoot, id) !== null and a meta state check.
Example fix
// before
await rebuildSystem(brandsRoot, id); // throws if brand.json missing
// after
const brand = readBrand(brandsRoot, id);
if (!brand) throw new HttpError(404, `brand not extracted yet: ${id}`);
if (!isExtractionTerminal(readMeta(brandsRoot, id))) {
throw new HttpError(409, 'extraction still running');
}
await rebuildSystem(brandsRoot, id); Defensive patterns
Strategy: validation
Validate before calling
import { readBrand, readMeta } from './store.js';
const brand = readBrand(brandsRoot, id);
if (!brand) throw new Error(`brand.json missing for ${id}`);
const meta = readMeta(brandsRoot, id);
if (!isExtractionTerminal(meta)) throw new Error('extraction not terminal'); Try / catch
try { await rebuildSystem(brandsRoot, id); }
catch (e) {
if (String(e.message).startsWith('brand.json not found for brand')) {
return res.status(404).json({ error: e.message });
}
throw e;
} Prevention
- Wait for extraction to reach the terminal state before rebuild.
- Surface 404 for a missing brand.json rather than letting rebuildSystem throw.
- Re-extract rather than hand-repairing corrupted brand.json.
When it happens
Trigger: rebuildSystem(brandsRoot, id) where the brand dir exists but brand.json was never written (extraction started but did not finish), was deleted, is corrupted JSON (readBrand swallows parse errors and returns null), or the id points at a dir that pre-dates the brand.json schema.
Common situations: Rebuild invoked on a still-extracting brand; rebuild after a partial/crashed extraction; brand.json deleted by hand; an old fixture dir lacking brand.json; race between delete and rebuild.
Related errors
- invalid brand id: ${id}
- invalid brand id: ${id}
- proposal patch.after markdown is required
- brand not found: ${opts.id}
- brand.json not found in the extraction project — the agent h
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/f5229d2c223a4758.
Report an issue: GitHub.