tailwindlabs/tailwindcss · error · Error

Cannot apply unprefixed utility class `${candidate}`. Did yo

Error message

Cannot apply unprefixed utility class `${candidate}`. Did you mean `${designSystem.theme.prefix}:${candidate}`?

What it means

Thrown during candidate compilation inside `@apply` when a `prefix` is configured on the design system theme but the candidate being applied does not start with that prefix. Tailwind requires prefixed utilities everywhere (including `@apply`) so the candidate is rejected and the user is told the likely intended prefixed form.

Source

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

      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, {
          respectImportant: false,
          onInvalidCandidate: (candidate) => {
            // When using prefix, make sure prefix is used in candidate
            if (designSystem.theme.prefix && !candidate.startsWith(designSystem.theme.prefix)) {
              throw new Error(
                `Cannot apply unprefixed utility class \`${candidate}\`. Did you mean \`${designSystem.theme.prefix}:${candidate}\`?`,
              )
            }

            // When the utility is blocklisted, let the user know
            //
            // Note: `@apply` is processed before handling incoming classes from
            // template files. This means that the `invalidCandidates` set will
            // only contain explicit classes via:
            //
            // - `blocklist` from a JS config
            // - `@source not inline(…)`
            if (designSystem.invalidCandidates.has(candidate)) {
              throw new Error(
                `Cannot apply utility class \`${candidate}\` because it has been explicitly disabled: https://tailwindcss.com/docs/detecting-classes-in-source-files#explicitly-excluding-classes`,
              )
            }

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Prefix the utility in the `@apply`: change `@apply flex` to `@apply tw:flex` (using your configured prefix).
  2. If you do not actually want a prefix, remove the `prefix` configuration from your `@import "tailwindcss"` options or JS config.
  3. Use the suggested `${prefix}:${candidate}` form printed in the error message verbatim.

Example fix

// before
@import "tailwindcss" prefix(tw);
.btn { @apply flex; }
// after
@import "tailwindcss" prefix(tw);
.btn { @apply tw:flex; }
Defensive patterns

Strategy: validation

Validate before calling

const prefix = designSystem.theme.prefix;
function assertPrefixed(candidates) {
  if (!prefix) return;
  for (const c of candidates) {
    if (!c.startsWith(prefix + ':') && !c.startsWith(prefix)) {
      throw new Error(`Candidate ${c} missing prefix ${prefix}`);
    }
  }
}
// assertPrefixed(['tw:flex']);

Try / catch

try { designSystem.compileAst(nodes) } catch (e) {
  if (/unprefixed utility class/.test(e.message)) { /* suggest prefix */ }
  else throw e;
}

Prevention

When it happens

Trigger: Configuring `prefix: 'tw'` (via CSS `@import` prefix option or JS config) and then writing `@apply flex;` instead of `@apply tw:flex;`. Fires in `onInvalidCandidate` only when `designSystem.theme.prefix` is truthy and `!candidate.startsWith(prefix)`.

Common situations: Setting a prefix for design-system isolation and forgetting it inside component CSS; copy-pasting utility classes from a non-prefixed project into a prefixed one.

Related errors


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