tailwindlabs/tailwindcss · error · Error

You cannot use `@apply` with both mixins and utilities. Plea

Error message

You cannot use `@apply` with both mixins and utilities. Please move `@apply ${list}` into a separate rule.

What it means

During `@apply` substitution the walker distinguishes normal idents (utilities) from dashed idents (CSS `@mixin`-style references per css-mixins-1). If a single `@apply` rule mixes both kinds, the behavior is ambiguous between utility expansion and literal mixin emission, which is invalid. The walker collects the dashed idents, joins them, and tells the user to move them into a separate rule.

Source

Thrown at packages/tailwindcss/src/apply.ts:199

        offset += part.length
      }

      if (dashedIdents.length) {
        // If we have an `@apply` that only consists of dashed idents then the
        // user is intending to use a CSS mixin:
        // https://drafts.csswg.org/css-mixins-1/#apply-rule
        //
        // These are not considered utilities and need to be emitted literally.
        if (normalIdents.length === 0) return WalkAction.Skip

        // If we find a dashed ident *here* it means that someone is trying
        // to use mixins and our `@apply` behavior together.
        //
        // This is invalid and the rules must be written separately. Let the
        // user know they need to move them into a separate rule.
        let list = dashedIdents.join(' ')

        throw new Error(
          `You cannot use \`@apply\` with both mixins and utilities. Please move \`@apply ${list}\` into a separate rule.`,
        )
      }

      let hasBody = child.nodes.length > 0

      if (hasBody && normalIdents.length) {
        let list = normalIdents.join(' ')

        throw new Error(`The rule \`@apply ${list}\` must not have a body.`)
      }

      // Replace the `@apply` rule with the actual utility classes
      {
        // Parse the candidates to an AST that we can replace the `@apply` rule
        // with.
        let candidates = Object.keys(candidateOffsets)
        let compiled = compileCandidates(candidates, designSystem, {

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Split the rule: keep `@apply <utilities>` in one rule and `@apply --mixin` in another.
  2. Use Tailwind's `@utility` to define the reusable styles instead of a dashed mixin.
  3. Remove the dashed ident if it was unintentional.

Example fix

/* before */
.btn { @apply p-4 rounded --my-mixin; }

/* after */
.btn { @apply p-4 rounded; }
.btn { @apply --my-mixin; }
Defensive patterns

Strategy: validation

Validate before calling

function assertNoMixedApply(params: string) {
  const dashed = params.split(/\s+/).filter(t => t.startsWith('--'))
  const normal = params.split(/\s+/).filter(t => t && !t.startsWith('--'))
  if (dashed.length && normal.length) {
    throw new Error(`@apply mixes utilities and mixins (${dashed.join(' ')}); split into separate rules`)
  }
}

Type guard

function isDashedIdent(token: string): boolean { return token.startsWith('--') }

Prevention

When it happens

Trigger: `@apply flex --my-mixin` or `.x { @apply p-4 --card; }` — a rule whose `@apply` params contain both a utility name and a `--dashed` ident. The dashed-ident branch at apply.ts:199 throws with the offending list.

Common situations: Confusing CSS native `@apply` (mixins) with Tailwind's `@apply` (utilities) in the same rule, or attempting to apply a custom property mixin alongside utilities.

Related errors


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