{"record":{"id":"32a5f24a98f256e3","repo":"CherryHQ/cherry-studio","slug":"theme-contract-variable-catalog-is-missing-mi","errorCode":null,"errorMessage":"[theme-contract] variable catalog is missing: ${missing.join(', ')}","messagePattern":"\\[theme-contract\\] variable catalog is missing: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/scripts/validate-theme-contract.ts","lineNumber":303,"sourceCode":"      const validNamespace =\n        reference.startsWith('--cs-') || officialVariables.has(reference) || productVariables.has(reference)\n      if (!validNamespace) {\n        throw new Error(`[theme-contract] product ${declaration.name} has invalid dependency ${reference}`)\n      }\n    }\n  }\n}\n\nfunction assertCatalogCoverage(sources: ThemeContractSources): void {\n  const requiredNames = [\n    ...RUNTIME_THEME_INPUT_TOKENS.map((token) => `--cs-theme-${token}`),\n    ...SHADCN_VARIABLE_TOKENS.map((token) => `--${token}`),\n    ...CHERRY_PRODUCT_VARIABLE_TOKENS.map((token) => `--${token}`)\n  ]\n  const missing = requiredNames.filter((name) => !sources.variableCatalog.includes(`\\`${name}\\``))\n\n  if (missing.length > 0) {\n    throw new Error(`[theme-contract] variable catalog is missing: ${missing.join(', ')}`)\n  }\n}\n\nexport function validateThemeContractSources(sources: ThemeContractSources): void {\n  assertUnique('runtime theme inputs', RUNTIME_THEME_INPUT_TOKENS)\n  assertUnique('Shadcn variables', SHADCN_VARIABLE_TOKENS)\n  assertUnique('product variables', CHERRY_PRODUCT_VARIABLE_TOKENS)\n  assertUnique('Tailwind product colors', CHERRY_PRODUCT_COLOR_TOKENS)\n  assertUnique('compatibility semantic colors', COMPATIBILITY_SEMANTIC_COLOR_TOKENS)\n  assertUnique('compatibility status colors', COMPATIBILITY_STATUS_COLOR_TOKENS)\n  assertUnique('compatibility colors', COMPATIBILITY_COLOR_TOKENS)\n\n  const productVariables = new Set<string>(CHERRY_PRODUCT_VARIABLE_TOKENS)\n  const shadcnVariables = new Set<string>(SHADCN_VARIABLE_TOKENS)\n  const shadcnVariableNames = new Set<string>(SHADCN_VARIABLE_TOKENS.map((token) => `--${token}`))\n  const productVariableNames = new Set<string>(CHERRY_PRODUCT_VARIABLE_TOKENS.map((token) => `--${token}`))\n  const canonicalColors = new Set<string>([...SHADCN_COLOR_TOKENS, ...CHERRY_PRODUCT_COLOR_TOKENS])\n","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/ui/scripts/validate-theme-contract.ts#L285-L321","documentation":"Thrown by assertCatalogCoverage when the documentation file docs/variable-catalog.md does not contain a backtick-quoted mention of every required contract variable (all runtime inputs, Shadcn variables, and product variables). The catalog is the public documentation surface; the validator guarantees it stays in sync with the code-defined registries so no variable ships undocumented.","triggerScenarios":"Adding a token to SHADCN_VARIABLE_TOKENS, CHERRY_PRODUCT_VARIABLE_TOKENS, or RUNTIME_THEME_INPUT_TOKENS in scripts/theme-contract.ts without adding a matching `--name` entry in packages/ui/docs/variable-catalog.md; editing the catalog and dropping a line.","commonSituations":"Extending the contract with a new role and forgetting to document it; regenerated/edited catalog that lost entries.","solutions":["Open packages/ui/docs/variable-catalog.md and add each missing variable as a backtick-quoted literal exactly as listed (e.g. `--success`).","Verify the spelling matches the message character-for-character (the check searches for the exact `${name}` inside backticks).","Re-run `pnpm --filter @cherrystudio/ui theme:check`."],"exampleFix":"// before — variable-catalog.md is missing `--success`\n// after\n| success | `--success` | product feedback success |","handlingStrategy":"validation","validationCode":"// Verify every required name appears backtick-quoted in the catalog before validating.\nconst required = [...RUNTIME_THEME_INPUT_TOKENS.map((t) => `--cs-theme-${t}`), ...SHADCN_VARIABLE_TOKENS.map((t) => `--${t}`), ...CHERRY_PRODUCT_VARIABLE_TOKENS.map((t) => `--${t}`)]\nconst missing = required.filter((n) => !sources.variableCatalog.includes(``${n}``))\nif (missing.length) throw new Error(`catalog missing: ${missing.join(', ')}`)","typeGuard":null,"tryCatchPattern":"try {\n  validateThemeContractSources(sources)\n} catch (error) {\n  if (error instanceof Error && /variable catalog is missing/.test(error.message)) {\n    console.error(error.message)\n    process.exitCode = 1\n    return\n  }\n  throw error\n}","preventionTips":["Whenever you add a token to any registry in scripts/theme-contract.ts, add a backtick-quoted `--name` line to packages/ui/docs/variable-catalog.md in the same commit.","Spell the variable name exactly as the registry produces it.","Run theme:check after editing the catalog."],"tags":["theme-contract","css","build","validation","docs"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}