CherryHQ/cherry-studio · error · Error
[theme-contract] compatibility color ${token} overlaps the c
Error message
[theme-contract] compatibility color ${token} overlaps the canonical color contract What it means
Thrown by validateThemeContractSources when a token in COMPATIBILITY_COLOR_TOKENS (the frozen, shrink-only legacy Tailwind compatibility surface) also appears in the canonical color surface (SHADCN_COLOR_TOKENS or CHERRY_PRODUCT_COLOR_TOKENS). Compatibility tokens are a separate legacy namespace and must not overlap canonical colors, otherwise the same name would mean two different things depending on context.
Source
Thrown at packages/ui/scripts/validate-theme-contract.ts:335
const shadcnVariables = new Set<string>(SHADCN_VARIABLE_TOKENS)
const shadcnVariableNames = new Set<string>(SHADCN_VARIABLE_TOKENS.map((token) => `--${token}`))
const productVariableNames = new Set<string>(CHERRY_PRODUCT_VARIABLE_TOKENS.map((token) => `--${token}`))
const canonicalColors = new Set<string>([...SHADCN_COLOR_TOKENS, ...CHERRY_PRODUCT_COLOR_TOKENS])
for (const token of CHERRY_PRODUCT_VARIABLE_TOKENS) {
if (shadcnVariables.has(token)) {
throw new Error(`[theme-contract] product variable ${token} overlaps the official Shadcn contract`)
}
}
for (const token of CHERRY_PRODUCT_COLOR_TOKENS) {
if (!productVariables.has(token)) {
throw new Error(`[theme-contract] Tailwind product color ${token} is missing from the product contract`)
}
}
for (const token of COMPATIBILITY_COLOR_TOKENS) {
if (canonicalColors.has(token)) {
throw new Error(`[theme-contract] compatibility color ${token} overlaps the canonical color contract`)
}
}
assertCompatibilityTokensDeclared(
'compatibility semantic colors',
COMPATIBILITY_SEMANTIC_COLOR_TOKENS,
sources.providerColors,
'tokens/colors/providers.css'
)
assertCompatibilityTokensDeclared(
'compatibility status colors',
COMPATIBILITY_STATUS_COLOR_TOKENS,
sources.statusLegacyColors,
'tokens/colors/status-legacy.css'
)
const shadcnRootDeclarations = buildDeclarationMap([['shadcn.css', sources.shadcn]], ':root')
assertRequiredDeclarations('Shadcn contract in shadcn.css', shadcnRootDeclarations, SHADCN_VARIABLE_TOKENS, '--')
for (const declaration of extractDeclarations(sources.shadcn, 'shadcn.css')) {View on GitHub (pinned to 726446b54c)
Solutions
- Pick a distinct compatibility-only name that does not appear in SHADCN_COLOR_TOKENS or CHERRY_PRODUCT_COLOR_TOKENS.
- If the canonical role is what you actually want, remove the token from COMPATIBILITY_COLOR_TOKENS and use the canonical color instead.
- Re-run `pnpm --filter @cherrystudio/ui theme:check`.
Example fix
// before — theme-contract.ts export const COMPATIBILITY_SEMANTIC_COLOR_TOKENS = ['background', ...] as const // 'background' is in SHADCN_COLOR_TOKENS -> collision // after — use a compatibility-only name export const COMPATIBILITY_SEMANTIC_COLOR_TOKENS = ['legacy-surface', ...] as const
Defensive patterns
Strategy: validation
Validate before calling
// Compatibility tokens must not collide with canonical colors.
const canonical = new Set([...SHADCN_COLOR_TOKENS, ...CHERRY_PRODUCT_COLOR_TOKENS])
const overlap = COMPATIBILITY_COLOR_TOKENS.filter((t) => canonical.has(t))
if (overlap.length) throw new Error(`compatibility tokens overlap canonical: ${overlap.join(', ')}`) Try / catch
try {
validateThemeContractSources(sources)
} catch (error) {
if (error instanceof Error && /compatibility color .* overlaps the canonical color contract/.test(error.message)) {
console.error(error.message)
process.exitCode = 1
return
}
throw error
} Prevention
- Treat COMPATIBILITY_COLOR_TOKENS as shrink-only: prefer removing over adding.
- Before adding a compatibility token, verify it is absent from SHADCN_COLOR_TOKENS and CHERRY_PRODUCT_COLOR_TOKENS.
- Use a distinct legacy-only name to avoid future canonical collisions.
When it happens
Trigger: Adding 'background' (a canonical color) to COMPATIBILITY_SEMANTIC_COLOR_TOKENS; reintroducing a legacy utility name that has since become canonical.
Common situations: Reviving an old Tailwind utility class without checking it now collides with a canonical token; growing the compatibility list when it is supposed to shrink only.
Related errors
- [theme-contract] theme-input.css declares unregistered runti
- [theme-contract] product variable ${token} overlaps the offi
- [theme-contract] Tailwind product color ${token} is missing
- [theme-contract] shadcn.css declares unregistered Shadcn var
- [theme-contract] product.css declares unregistered product v
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/6b1de5e58dfc1bdf.
Report an issue: GitHub.