tailwindlabs/tailwindcss · error · Error

`@utility ${node.params}` is empty. Utilities should include

Error message

`@utility ${node.params}` is empty. Utilities should include at least one property.

What it means

Thrown when an `@utility` at-rule has zero child nodes (`node.nodes.length === 0`). Tailwind requires every utility to declare at least one CSS property so it produces output; an empty block is almost always a typo or an unfinished edit. The check runs after the nesting guard and before `createCssUtility`.

Source

Thrown at packages/tailwindcss/src/index.ts:230

          root = {
            base: (ctx.context.sourceBase as string) ?? (ctx.context.base as string),
            pattern: path.slice(1, -1),
          }
        }
      }

      utilitiesNode = node
      features |= Features.Utilities
    }

    // Collect custom `@utility` at-rules
    if (node.name === '@utility') {
      if (ctx.parent !== null) {
        throw new Error('`@utility` cannot be nested.')
      }

      if (node.nodes.length === 0) {
        throw new Error(
          `\`@utility ${node.params}\` is empty. Utilities should include at least one property.`,
        )
      }

      let utility = createCssUtility(node)
      if (utility === null) {
        if (!node.params.endsWith('-*')) {
          if (node.params.endsWith('*')) {
            throw new Error(
              `\`@utility ${node.params}\` defines an invalid utility name. A functional utility must end in \`-*\`.`,
            )
          } else if (node.params.includes('*')) {
            throw new Error(
              `\`@utility ${node.params}\` defines an invalid utility name. The dynamic portion marked by \`-*\` must appear once at the end.`,
            )
          }
        }

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Add at least one CSS declaration inside the block, e.g. `@utility card { padding: 1rem; }`.
  2. If the utility is no longer needed, remove the entire `@utility` at-rule.
  3. Re-check that your editor/CI did not strip the body during formatting.

Example fix

/* before */
@utility card { }

/* after */
@utility card {
  padding: 1rem;
  border-radius: 0.5rem;
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty @utility blocks before compiling.
import postcss from 'postcss'

function validateUtilityHasBody(css: string): string[] {
  const errors: string[] = []
  postcss.parse(css).walkAtRules('@utility', (rule) => {
    if (rule.nodes.length === 0) {
      errors.push(`@utility ${rule.params} is empty`)
    }
  })
  return errors
}

Prevention

When it happens

Trigger: Writing `@utility card { }` with no declarations, or a block containing only comments/whitespace that parse to zero nodes.

Common situations: Stubbing out a utility placeholder and forgetting to fill it; deleting the body during a refactor and leaving the at-rule behind; copy-paste that dropped the inner rules.

Related errors


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