CherryHQ/cherry-studio · error · Error
[theme-contract] renderer stylesheet ${fileName} cannot use
Error message
[theme-contract] renderer stylesheet ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables directly What it means
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.
Source
Thrown at packages/ui/scripts/validate-migration-contract.ts:194
const rendererTheme = stripComments(sources.rendererTheme)
if (rendererTheme.includes('legacy-vars.css')) {
throw new Error('[theme-contract] renderer theme cannot import the removed legacy compatibility layer')
}
if (rendererTheme.includes('--app-')) {
throw new Error(
'[theme-contract] renderer theme entry cannot own --app-* variables; keep host-local values in a dedicated stylesheet'
)
}
if (/@theme(?:\s+inline)?\s*\{/.test(rendererTheme)) {
throw new Error('[theme-contract] renderer theme must use the shared generated Tailwind adapter')
}
for (const [fileName, source] of Object.entries(sources.rendererStyles)) {
const adapterVariable = stripComments(source).match(TAILWIND_ADAPTER_VARIABLE_PATTERN)?.[0]
if (adapterVariable) {
throw new Error(
`[theme-contract] renderer stylesheet ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables directly`
)
}
}
for (const [fileName, source] of Object.entries(sources.rendererTypeScriptSources)) {
const adapterVariable = source.includes('--color-') ? findTypeScriptAdapterVariable(source, fileName) : undefined
if (adapterVariable) {
throw new Error(
`[theme-contract] renderer TypeScript source ${fileName} cannot use Tailwind adapter variable ${adapterVariable}; use runtime semantic variables or Tailwind utilities`
)
}
const disallowedWrite = findTypeScriptDisallowedThemeWrite(source, fileName)
if (disallowedWrite) {
throw new Error(
`[theme-contract] renderer TypeScript source ${fileName} cannot write shared theme variable ${disallowedWrite}; use a registered --cs-theme-* input or an owner-local --app-* variable`View on GitHub (pinned to 726446b54c)
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.
Example fix
/* before — renderer .css file */
.my-component {
background: var(--color-blue-500);
border-color: var(--color-red-300);
}
/* after — use semantic variables */
.my-component {
background: var(--primary);
border-color: var(--destructive);
} Defensive patterns
Strategy: validation
Validate before calling
// Scan renderer .css files for --color-* adapter variables before committing
import { readFileSync } from 'node:fs'
function checkNoAdapterVars(cssPath: string): void {
const source = readFileSync(cssPath, 'utf8').replace(/\/\*[\s\S]*?\*\//g, '')
const match = source.match(/--color-[a-z0-9-]*/)
if (match) {
throw new Error(`${cssPath} uses adapter variable ${match[0]} — use semantic variables instead`)
}
} Prevention
- 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.
When it happens
Trigger: 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-]*/.
Common situations: 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.
Related errors
- [theme-contract] renderer theme must use the shared generate
- [theme-contract] renderer TypeScript source ${fileName} cann
- [theme-contract] ${sourceName} declares invalid custom prope
- [theme-contract] ${sourceName} references invalid custom pro
- [theme-contract] unsupported @import syntax: ${importValue}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/92f22643b6e0b275.
Report an issue: GitHub.