CherryHQ/cherry-studio · error · Error

[theme-contract] runtime input ${declaration.name} cannot de

Error message

[theme-contract] runtime input ${declaration.name} cannot depend on upper-layer ${reference}

What it means

Thrown by assertLayerDependencies when a runtime-input declaration (--cs-theme-*) in theme-input.css references an upper-layer variable: an official Shadcn variable, a product variable, or a Tailwind adapter variable (--color-*). Runtime inputs sit between foundation and Shadcn; they translate foundation values for the host and must only depend on foundation or other runtime inputs.

Source

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

          reference.startsWith(runtimeVariablePrefix) ||
          officialVariables.has(reference) ||
          productVariables.has(reference) ||
          reference.startsWith('--color-') ||
          reference.startsWith('--app-')
        ) {
          throw new Error(`[theme-contract] foundation ${declaration.name} cannot depend on upper-layer ${reference}`)
        }
      }
    }
  }

  for (const declaration of extractDeclarations(sources.themeInput, 'theme-input.css')) {
    if (!runtimeVariables.has(declaration.name)) {
      throw new Error(`[theme-contract] theme-input.css declares unregistered runtime input ${declaration.name}`)
    }
    for (const reference of extractReferences(declaration.value, declaration.source)) {
      if (officialVariables.has(reference) || productVariables.has(reference) || reference.startsWith('--color-')) {
        throw new Error(`[theme-contract] runtime input ${declaration.name} cannot depend on upper-layer ${reference}`)
      }
      if (reference.startsWith('--app-')) {
        throw new Error(`[theme-contract] runtime input ${declaration.name} cannot depend on host-local ${reference}`)
      }
    }
  }

  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}`)
      }
    }
  }

View on GitHub (pinned to 726446b54c)

Solutions

  1. Re-point the runtime input at a foundation-layer variable (--cs-* or a primitive).
  2. If the dependency on an upper layer is intentional, the relationship is inverted: move the logic so the upper layer references the runtime input (e.g. shadcn.css `--primary: var(--cs-theme-primary)`), not the reverse.
  3. Re-run `pnpm --filter @cherrystudio/ui theme:check`.

Example fix

// before (theme-input.css)
--cs-theme-primary: var(--primary);
// after — runtime input depends only on foundation
--cs-theme-primary: var(--cs-primary);
Defensive patterns

Strategy: validation

Validate before calling

// Runtime inputs must not reference shadcn/product/adapter variables.
const upperLayer = (ref: string) => ref.startsWith('--color-') || SHADCN_VARIABLE_TOKENS.includes(ref.slice(2) as never) || CHERRY_PRODUCT_VARIABLE_TOKENS.includes(ref.slice(2) as never)
for (const [, ref] of sources.themeInput.matchAll(/var\(\s*(--[a-z0-9-]+)/g)) {
  if (upperLayer(ref)) throw new Error(`runtime input depends on upper layer ${ref}`)
}

Try / catch

try {
  validateThemeContractSources(sources)
} catch (error) {
  if (error instanceof Error && /runtime input .* cannot depend on upper-layer/.test(error.message)) {
    console.error(error.message)
    process.exitCode = 1
    return
  }
  throw error
}

Prevention

When it happens

Trigger: Replacing `var(--cs-primary)` with `var(--primary)` in theme-input.css; setting `--cs-theme-primary: var(--success);` (product dep); `--cs-theme-primary: var(--color-blue-500);` (adapter dep).

Common situations: Trying to make a runtime input follow a Shadcn/product role instead of a foundation primitive; copy-pasting a value reference from the wrong layer.

Related errors


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