{"record":{"id":"92f22643b6e0b275","repo":"CherryHQ/cherry-studio","slug":"theme-contract-renderer-stylesheet-filename-c","errorCode":null,"errorMessage":"[theme-contract] renderer stylesheet ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables directly","messagePattern":"\\[theme-contract\\] renderer stylesheet (.+?) cannot use Tailwind adapter variable (.+?); use runtime semantic variables directly","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/scripts/validate-migration-contract.ts","lineNumber":194,"sourceCode":"\n  const rendererTheme = stripComments(sources.rendererTheme)\n  if (rendererTheme.includes('legacy-vars.css')) {\n    throw new Error('[theme-contract] renderer theme cannot import the removed legacy compatibility layer')\n  }\n  if (rendererTheme.includes('--app-')) {\n    throw new Error(\n      '[theme-contract] renderer theme entry cannot own --app-* variables; keep host-local values in a dedicated stylesheet'\n    )\n  }\n  if (/@theme(?:\\s+inline)?\\s*\\{/.test(rendererTheme)) {\n    throw new Error('[theme-contract] renderer theme must use the shared generated Tailwind adapter')\n  }\n\n  for (const [fileName, source] of Object.entries(sources.rendererStyles)) {\n    const adapterVariable = stripComments(source).match(TAILWIND_ADAPTER_VARIABLE_PATTERN)?.[0]\n\n    if (adapterVariable) {\n      throw new Error(\n        `[theme-contract] renderer stylesheet ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables directly`\n      )\n    }\n  }\n\n  for (const [fileName, source] of Object.entries(sources.rendererTypeScriptSources)) {\n    const adapterVariable = source.includes('--color-') ? findTypeScriptAdapterVariable(source, fileName) : undefined\n\n    if (adapterVariable) {\n      throw new Error(\n        `[theme-contract] renderer TypeScript source ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables or Tailwind utilities`\n      )\n    }\n\n    const disallowedWrite = findTypeScriptDisallowedThemeWrite(source, fileName)\n    if (disallowedWrite) {\n      throw new Error(\n        `[theme-contract] renderer TypeScript source ${fileName} cannot write shared theme variable ${disallowedWrite}; use a registered --cs-theme-* input or an owner-local --app-* variable`","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/ui/scripts/validate-migration-contract.ts#L176-L212","documentation":"Thrown by the theme migration contract validator when any renderer stylesheet (.css file under src/renderer/) references a Tailwind adapter variable matching --color-[a-z0-9-]*. The contract requires renderer CSS to use runtime semantic variables (e.g., var(--background), var(--foreground)) directly rather than the low-level --color-* adapter tokens, which are an internal implementation detail of the generated Tailwind adapter.","triggerScenarios":"A .css file under src/renderer/ contains a reference to a --color-* custom property (e.g., var(--color-primary-500) or --color-red-500: #f00). The validator scans each renderer stylesheet after stripping comments and matches against /--color-[a-z0-9-]*/.","commonSituations":"A developer hardcodes a Tailwind palette color (e.g., var(--color-blue-500)) instead of using the semantic token (e.g., var(--primary)). Copy-pasting from the generated adapter output into renderer CSS. Attempting to reference a primitive color directly rather than through the semantic layer. A migration from the old system that left raw --color-* references behind.","solutions":["Replace the --color-* reference with the corresponding semantic variable (e.g., var(--color-primary-500) → var(--primary)).","If no semantic variable exists for the use case, add one to the product contract in packages/ui/src/styles/product.css and reference that instead.","If the reference is in a style that should use Tailwind utility classes instead of CSS variables, switch to a utility class (e.g., bg-primary).","Run the validator to confirm: npx tsx packages/ui/scripts/validate-migration-contract.ts."],"exampleFix":"/* before — renderer .css file */\n.my-component {\n  background: var(--color-blue-500);\n  border-color: var(--color-red-300);\n}\n\n/* after — use semantic variables */\n.my-component {\n  background: var(--primary);\n  border-color: var(--destructive);\n}","handlingStrategy":"validation","validationCode":"// Scan renderer .css files for --color-* adapter variables before committing\nimport { readFileSync } from 'node:fs'\n\nfunction checkNoAdapterVars(cssPath: string): void {\n  const source = readFileSync(cssPath, 'utf8').replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n  const match = source.match(/--color-[a-z0-9-]*/)\n  if (match) {\n    throw new Error(`${cssPath} uses adapter variable ${match[0]} — use semantic variables instead`)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use semantic CSS variables (var(--primary), var(--background), etc.) instead of raw --color-* tokens in renderer CSS.","Keep a reference of available semantic variables from packages/ui/src/styles/contract.md or the variable catalog.","Run the migration contract validator as part of your CI pipeline.","When copying CSS from external sources, replace any --color-* references with semantic equivalents."],"tags":["theme-contract","build-validation","tailwind","css","semantic-tokens"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}