CherryHQ/cherry-studio · error · Error
[theme-contract] product variable ${token} overlaps the offi
Error message
[theme-contract] product variable ${token} overlaps the official Shadcn contract What it means
Thrown by validateThemeContractSources when a token in CHERRY_PRODUCT_VARIABLE_TOKENS also appears in SHADCN_VARIABLE_TOKENS. Product variables must not collide with the official Shadcn namespace, because a shared name would silently shadow an official role and break the separation between the upstream contract and Cherry-specific extensions.
Source
Thrown at packages/ui/scripts/validate-theme-contract.ts:324
export function validateThemeContractSources(sources: ThemeContractSources): void {
assertUnique('runtime theme inputs', RUNTIME_THEME_INPUT_TOKENS)
assertUnique('Shadcn variables', SHADCN_VARIABLE_TOKENS)
assertUnique('product variables', CHERRY_PRODUCT_VARIABLE_TOKENS)
assertUnique('Tailwind product colors', CHERRY_PRODUCT_COLOR_TOKENS)
assertUnique('compatibility semantic colors', COMPATIBILITY_SEMANTIC_COLOR_TOKENS)
assertUnique('compatibility status colors', COMPATIBILITY_STATUS_COLOR_TOKENS)
assertUnique('compatibility colors', COMPATIBILITY_COLOR_TOKENS)
const productVariables = new Set<string>(CHERRY_PRODUCT_VARIABLE_TOKENS)
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'View on GitHub (pinned to 726446b54c)
Solutions
- Rename the product token to a non-colliding, product-specific name (e.g. 'background-subtle' instead of 'background').
- If the role genuinely belongs to the official Shadcn contract, remove it from CHERRY_PRODUCT_VARIABLE_TOKENS and add it to SHADCN_VARIABLE_TOKENS instead (then author it in shadcn.css).
- Re-run `pnpm --filter @cherrystudio/ui theme:check`.
Example fix
// before — theme-contract.ts export const CHERRY_PRODUCT_VARIABLE_TOKENS = ['background', ...] as const // after — rename to a product-specific token export const CHERRY_PRODUCT_VARIABLE_TOKENS = ['background-subtle', ...] as const
Defensive patterns
Strategy: validation
Validate before calling
// Reject tokens present in both product and shadcn registries.
const shadcn = new Set(SHADCN_VARIABLE_TOKENS)
const overlap = CHERRY_PRODUCT_VARIABLE_TOKENS.filter((t) => shadcn.has(t))
if (overlap.length) throw new Error(`product tokens overlap shadcn: ${overlap.join(', ')}`) Try / catch
try {
validateThemeContractSources(sources)
} catch (error) {
if (error instanceof Error && /product variable .* overlaps the official Shadcn contract/.test(error.message)) {
console.error(error.message)
process.exitCode = 1
return
}
throw error
} Prevention
- Before naming a new product token, check it is not already in SHADCN_VARIABLE_TOKENS.
- Keep product names role-specific (e.g. -subtle, -strong suffixes) to avoid collisions with official Shadcn roles.
- Run theme:check after editing either registry.
When it happens
Trigger: Adding 'background' (already a Shadcn token) to CHERRY_PRODUCT_VARIABLE_TOKENS in scripts/theme-contract.ts; adding a Shadcn color name like 'primary' as a product token.
Common situations: Adding a product role whose name happens to match an official Shadcn role; not checking the Shadcn list before naming a new product token.
Related errors
- [theme-contract] theme-input.css declares unregistered runti
- [theme-contract] Tailwind product color ${token} is missing
- [theme-contract] compatibility color ${token} overlaps the c
- [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/c500408780b62e20.
Report an issue: GitHub.