{"record":{"id":"5a49591f26bb6351","repo":"nexu-io/open-design","slug":"brand-json-failed-validation-errormessage-err","errorCode":null,"errorMessage":"brand.json failed validation: ${errorMessage(err)}","messagePattern":"brand\\.json failed validation: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/brands/index.ts","lineNumber":1354,"sourceCode":"  const brandJsonRaw = await readProjectTextOrNull(projectsRoot, projectId, 'brand.json');\n  if (brandJsonRaw === null) {\n    throw new Error(\n      'brand.json not found in the extraction project — the agent has not written the design system yet.',\n    );\n  }\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(brandJsonRaw);\n  } catch {\n    const block = extractJsonBlock(brandJsonRaw);\n    if (block === null) throw new Error('brand.json is not valid JSON.');\n    parsed = block;\n  }\n  let brand: Brand;\n  try {\n    brand = validateBrand(parsed, meta.sourceUrl);\n  } catch (err) {\n    throw new Error(`brand.json failed validation: ${errorMessage(err)}`);\n  }\n\n  // Pull the agent's downloaded assets into the brand workspace so the\n  // deterministic builder and the design system see them.\n  copyProjectDirToBrand(projectsRoot, projectId, brandsRoot, id, 'logos');\n  copyProjectDirToBrand(projectsRoot, projectId, brandsRoot, id, 'fonts');\n  copyProjectDirToBrand(projectsRoot, projectId, brandsRoot, id, 'imagery');\n\n  const guideMd =\n    (await readProjectTextOrNull(projectsRoot, projectId, 'BRAND.md')) ?? brandGuideMd(brand);\n\n  return finalizeBrandCore({ ...opts, id, projectId, meta, brand, guideMd });\n}\n\ninterface FinalizeBrandCoreOptions extends FinalizeBrandOptions {\n  /** Backing project to sync the finalized design system into. */\n  projectId: string;\n  /** Lifecycle record (already loaded by the caller). */","sourceCodeStart":1336,"sourceCodeEnd":1372,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/brands/index.ts#L1336-L1372","documentation":"Thrown by finalizeBrand when validateBrand(parsed, meta.sourceUrl) raises. The file parsed successfully (or was extracted from a fence) but its shape does not match the Brand schema (required keys missing, wrong types such as colors not being an array or typography not an object, bad color hex values, etc.). The wrapped errorMessage(err) names the specific failure.","triggerScenarios":"Required keys missing (no colors, no typography); colors entries missing hex; typography not an object; arrays where objects are expected; string fields that fail per-field validators.","commonSituations":"Agent produced partially-shaped JSON (filled some modules, left others malformed); schema version drift between the agent's prompt and the validator; manual edit that broke the shape.","solutions":["Read errorMessage(err) in the thrown message to identify the specific field, then fix that field in brand.json.","Re-run the extraction with a stricter prompt that emphasizes the required Brand schema.","If you constructed the JSON by hand, compare against a known-good Brand example before finalizing."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Reuse the same validator the daemon uses, before calling finalizeBrand.\nlet parsed: unknown;\ntry { parsed = JSON.parse(rawBrandJson); } catch { parsed = extractJsonBlock(rawBrandJson); }\nif (parsed !== null) {\n  try { validateBrand(parsed, sourceUrl); }\n  catch (err) { throw new Error(`Brand JSON would fail validation: ${errorMessage(err)}`); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await finalizeBrand(opts);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('brand.json failed validation: ')) {\n    const detail = err.message.slice('brand.json failed validation: '.length);\n    return unprocessableEntity(`Fix brand.json: ${detail}`);\n  }\n  throw err;\n}","preventionTips":["Read the wrapped errorMessage(err) — it identifies the failing field.","Keep the agent's prompt schema and the validateBrand schema in sync.","Validate the parsed object before finalizing so users get field-level errors early."],"tags":["brands","validation","schema","finalize"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}