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

  1. Replace the --color-* reference with the corresponding semantic variable (e.g., var(--color-primary-500) → var(--primary)).
  2. 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.
  3. 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).
  4. 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

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


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/92f22643b6e0b275. Report an issue: GitHub.