CherryHQ/cherry-studio · error · Error

[theme-contract] product ${declaration.name} has invalid dep

Error message

[theme-contract] product ${declaration.name} has invalid dependency ${reference}

What it means

Thrown by assertLayerDependencies when a declaration in product.css references a variable outside the allowed product-layer namespaces. Product variables may only reference --cs-* (foundation), official Shadcn variables (--background, --primary, etc.), or other product variables. Any other reference (e.g. --color-*, --app-*, or an undeclared name) is invalid.

Source

Thrown at packages/ui/scripts/validate-theme-contract.ts:288

  }

  for (const declaration of extractDeclarations(sources.shadcn, 'shadcn.css')) {
    if (declaration.name.startsWith(runtimeVariablePrefix)) {
      throw new Error(`[theme-contract] shadcn.css cannot own runtime input ${declaration.name}`)
    }
    for (const reference of extractReferences(declaration.value, declaration.source)) {
      if (productVariables.has(reference) || reference.startsWith('--color-') || reference.startsWith('--app-')) {
        throw new Error(`[theme-contract] Shadcn ${declaration.name} cannot depend on product/adapter ${reference}`)
      }
    }
  }

  for (const declaration of extractDeclarations(sources.product, 'product.css')) {
    for (const reference of extractReferences(declaration.value, declaration.source)) {
      const validNamespace =
        reference.startsWith('--cs-') || officialVariables.has(reference) || productVariables.has(reference)
      if (!validNamespace) {
        throw new Error(`[theme-contract] product ${declaration.name} has invalid dependency ${reference}`)
      }
    }
  }
}

function assertCatalogCoverage(sources: ThemeContractSources): void {
  const requiredNames = [
    ...RUNTIME_THEME_INPUT_TOKENS.map((token) => `--cs-theme-${token}`),
    ...SHADCN_VARIABLE_TOKENS.map((token) => `--${token}`),
    ...CHERRY_PRODUCT_VARIABLE_TOKENS.map((token) => `--${token}`)
  ]
  const missing = requiredNames.filter((name) => !sources.variableCatalog.includes(`\`${name}\``))

  if (missing.length > 0) {
    throw new Error(`[theme-contract] variable catalog is missing: ${missing.join(', ')}`)
  }
}

View on GitHub (pinned to 726446b54c)

Solutions

  1. Re-point the product variable at a valid namespace: a --cs-* foundation var, an official Shadcn var, or another product var.
  2. If you need a concrete color, declare it as a --cs-* primitive in foundation first, then reference that.
  3. Re-run `pnpm --filter @cherrystudio/ui theme:check`.

Example fix

// before (product.css)
--link: var(--color-blue-500);
// after — reference a foundation primitive
--link: var(--cs-blue-600);
Defensive patterns

Strategy: validation

Validate before calling

// product.css references must stay in --cs-*, shadcn, or product namespaces.
const valid = (ref: string) => ref.startsWith('--cs-') || SHADCN_VARIABLE_TOKENS.includes(ref.slice(2) as never) || CHERRY_PRODUCT_VARIABLE_TOKENS.includes(ref.slice(2) as never)
for (const [, ref] of sources.product.matchAll(/var\(\s*(--[a-z0-9-]+)/g)) {
  if (!valid(ref)) throw new Error(`product has invalid dependency ${ref}`)
}

Try / catch

try {
  validateThemeContractSources(sources)
} catch (error) {
  if (error instanceof Error && /product .* has invalid dependency/.test(error.message)) {
    console.error(error.message)
    process.exitCode = 1
    return
  }
  throw error
}

Prevention

When it happens

Trigger: `--link: var(--app-accent);` (host-local); `--link: var(--color-blue-500);` (Tailwind adapter); `--link: var(--some-random);` (undeclared).

Common situations: Repointing a product token at a Tailwind utility color or a host-injected variable during a redesign; typos in var() references.

Related errors


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