tailwindlabs/tailwindcss · error · Error

You have one or more stylesheets that are imported into a ut

Error message

You have one or more stylesheets that are imported into a utility layer and non-utility layer.
We cannot convert stylesheets under these conditions. Please look at the following stylesheets:
${lines.join('\n')}

What it means

During upgrade, the CSS analyzer tags each stylesheet as imported into a `utilities` layer, a non-utility layer, or both. Tailwind v4 requires a stylesheet to belong consistently to one layer category so it can rewrite `@tailwind utilities` semantics. If the same stylesheet is imported once into a utility layer and once elsewhere, the rewrite is ambiguous and the upgrade aborts with the offending stylesheet list.

Source

Thrown at packages/@tailwindcss-upgrade/src/codemods/css/analyze.ts:301

      // flag from each leaf.
      for (let [parent, children] of commonParents) {
        parent.isTailwindRoot = true

        for (let child of children) {
          if (parent === child) continue

          child.isTailwindRoot = false
        }
      }
      return
    }
  }

  {
    let error = `You have one or more stylesheets that are imported into a utility layer and non-utility layer.\n`
    error += `We cannot convert stylesheets under these conditions. Please look at the following stylesheets:\n`

    throw new Error(error + lines.join('\n'))
  }
}

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Consolidate each stylesheet to a single layer usage: import it into either the utilities layer or a regular layer, not both.
  2. Split the shared stylesheet into two files (one per layer) if both contexts are genuinely needed.
  3. Re-run the upgrade once the duplicate-layer imports are removed.

Example fix

/* before */
@import "./shared.css" layer(utilities);
@import "./shared.css";

/* after */
@import "./shared-utils.css" layer(utilities);
@import "./shared-base.css";
Defensive patterns

Strategy: validation

Validate before calling

// Audit stylesheet layer usage before upgrade
function findDuplicateLayerImports(cssFiles: { file: string; css: string }[]) {
  const seen = new Map<string, Set<string>>()
  for (const { file, css } of cssFiles) {
    for (const m of css.matchAll(/@import\s+["']([^"']+)["'](?:\s+layer\(([^)]+)\))?/g)) {
      const [, target, layer] = m
      const layers = seen.get(target) ?? new Set()
      const tag = layer ? `layer:${layer}` : 'layer:none'
      if (layers.has('mixed') || (layers.size && ![...layers].includes(tag) && (layer === 'utilities' || [...layers].some(l => l === 'layer:utilities')))) {
        console.warn(`Duplicate-layer import: ${target} in ${file}`)
      }
      layers.add(tag); seen.set(target, layers)
    }
  }
}

Prevention

When it happens

Trigger: A `styles.css` imported both as `@import 'x.css' layer(utilities)` and again as a plain `@import 'x.css'` (or into a different named layer) within the same project. The analyzer collects `lines` of offending imports and analyze.ts:301 throws.

Common situations: Shared/partial CSS files pulled into multiple layers across an app, or a design-system CSS imported both into Tailwind's utilities layer and a component layer.

Related errors


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