tailwindlabs/tailwindcss · error · Error
Cannot use `@variant` with variant: ${variant}
Error message
Cannot use `@variant` with variant: ${variant} What it means
Thrown by substituteAtVariant() when applyVariant() returns null, meaning the variant parsed successfully but could not be applied to the current node. This is distinct from [85]: the variant is known, but its application to the AST node failed — typically because the variant's compound/recursive logic cannot compose with the surrounding structure.
Source
Thrown at packages/tailwindcss/src/variants.ts:1310
: 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)
})
return features
}
View on GitHub (pinned to 16e94cbf7f)
Solutions
- Simplify the variant stack: try the variant alone to isolate which combination fails.
- If it is your custom variant, ensure its static/dynamic resolver always returns a valid selector (non-null).
- Check the variant's definition for missing branches; report a bug if a documented built-in variant triggers this.
- Try a different but equivalent variant ordering.
Example fix
/* before — applyVariant returns null for this combination */
@variant my-variant:hover { ... }
/* after — verify the custom variant returns a selector */
@custom-variant my-variant (&:where(.active));
@variant my-variant { ... } Defensive patterns
Strategy: try-catch
Validate before calling
// Limited pre-validation; applyVariant failure is structural // Best: test the variant in isolation first designSystem.parseVariant(name) // ensure non-null before stacking
Type guard
function variantApplies(
node: AstNode,
variant: Variant,
variants: Map<string, Variant>
): boolean {
return applyVariant(cloneAstNode(node), variant, variants) !== null
} Try / catch
try {
substituteAtVariant(ast, designSystem)
} catch (e) {
if (/Cannot use `@variant` with variant:/.test(String(e))) {
// simplify the stack and retry, or skip the problematic rule
}
} Prevention
- Simplify variant stacks to isolate which combination fails.
- Ensure custom variants always return a valid selector.
- Test variants individually before composing them.
When it happens
Trigger: Using a variant whose internal resolution returns null for the given node context — e.g. a custom variant with a static() strategy that doesn't apply, or stacking variants in an order that produces no valid selector. This is the fallback when parseVariant succeeds but applyVariant's machinery yields null.
Common situations: Authoring a custom @custom-variant that returns no valid selector for some inputs. Combining variants in unusual stacks. Edge cases in plugin-provided variants that don't handle all node shapes. This is rarer than [85] and often indicates a variant-definition bug rather than user error.
Related errors
- Cannot use `@variant` with empty variant
- Cannot use `@variant` with unknown variant: ${variant}
- Invalid theme value `${value}` for namespace `${key}`
- The rule `@apply ${list}` must not have a body.
- Cannot apply utility class `${candidate}` because the `${unk
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/98ec1e65d19a59ce.
Report an issue: GitHub.