tailwindlabs/tailwindcss · error · Error

Cannot use `@variant` with unknown variant: ${variant}

Error message

Cannot use `@variant` with unknown variant: ${variant}

What it means

Thrown by substituteAtVariant() when designSystem.parseVariant(variant) returns null, meaning the variant name is not registered in the design system. Every segment of a colon-separated variant stack must resolve to a known variant (hover, focus, md, dark, custom-variant, etc.). This fires after the empty-variant check, so the name is non-empty but unrecognized.

Source

Thrown at packages/tailwindcss/src/variants.ts:1305

      // nodes for sourcemap `dst` location information.
      let node = styleRule(
        '&',
        idx === compoundVariants.length - 1
          ? variantNode.nodes
          : variantNode.nodes.map(cloneAstNode),
      )

      let stackedVariants = segment(compoundVariant, ':')
      for (let i = stackedVariants.length - 1; i >= 0; --i) {
        let variant = stackedVariants[i].trim()

        if (!variant) {
          throw new Error(`Cannot use \`@variant\` with empty variant`)
        }

        let variantAst = designSystem.parseVariant(variant)
        if (variantAst === null) {
          throw new Error(`Cannot use \`@variant\` with unknown variant: ${variant}`)
        }

        let result = applyVariant(node, variantAst, designSystem.variants)
        if (result === null) {
          throw new Error(`Cannot use \`@variant\` with variant: ${variant}`)
        }
      }

      if (node.selector === '&') {
        nodes.push(...node.nodes)
      } else {
        nodes.push(node)
      }
    }

    // Update the variant at-rule node, to be the `&` rule node
    features |= Features.Variants
    return WalkAction.Replace(nodes)

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Register the variant first: '@custom-variant foo (&:is(.foo));' then use '@variant foo'.
  2. Fix the typo: 'hvoer' -> 'hover'.
  3. Confirm the variant is available (built-in or from a loaded plugin) in your Tailwind version.

Example fix

/* before — throws if 'tag' is undefined */
@variant tag {
  .x { display: none; }
}

/* after */
@custom-variant tag (&:is([data-tag]));
@variant tag {
  .x { display: none; }
}
Defensive patterns

Strategy: validation

Validate before calling

// Check a variant resolves before authoring @variant
const known = new Set(['hover','focus','active','md','lg','dark', /* ... */])
function variantExists(name: string): boolean {
  return known.has(name) || customVariants.has(name)
}
if (!variantExists(name)) {
  throw new Error(`Unknown variant '${name}' — register via @custom-variant`)
}

Type guard

function isKnownVariant(name: string, designSystem: DesignSystem): boolean {
  return designSystem.parseVariant(name) !== null
}

Prevention

When it happens

Trigger: Using '@variant foo { ... }' where 'foo' is neither a built-in variant nor a custom variant registered via @custom-variant. Referencing a variant before it is defined, or misspelling one (e.g. 'hvoer').

Common situations: Forgetting to declare a custom variant with @custom-variant before using it in @variant. Typos in variant names. Assuming a plugin-registered variant is available when the plugin isn't loaded. Ordering issue where @variant appears before the @custom-variant definition in source order.

Related errors


AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12). Data as JSON: /api/errors/0ceda67346aa7275. Report an issue: GitHub.