tailwindlabs/tailwindcss · error · Error

`@config` cannot be nested.

Error message

`@config` cannot be nested.

What it means

Thrown when an `@config` at-rule is nested inside another rule (`ctx.parent !== null`). Like `@plugin`, `@config` must be top-level so the referenced JS config loads at the correct phase.

Source

Thrown at packages/tailwindcss/src/compat/apply-compat-hooks.ts:133

          base: ctx.context.base as string,
          reference: !!ctx.context.reference,
          src: node.src,
        },
        Object.keys(options).length > 0 ? options : null,
      ])

      features |= Features.JsPluginCompat
      return WalkAction.Replace([])
    }

    // Collect paths from `@config` at-rules
    if (node.name === '@config') {
      if (node.nodes.length > 0) {
        throw new Error('`@config` cannot have a body.')
      }

      if (ctx.parent !== null) {
        throw new Error('`@config` cannot be nested.')
      }

      configPaths.push({
        id: node.params.slice(1, -1),
        base: ctx.context.base as string,
        reference: !!ctx.context.reference,
        src: node.src,
      })
      features |= Features.JsPluginCompat
      return WalkAction.Replace([])
    }
  })

  registerLegacyUtilities(designSystem)

  // Override `resolveThemeValue` with a version that is backwards compatible
  // with dot notation paths like `colors.red.500`. We could do this by default
  // in `resolveThemeValue` but handling it here keeps all backwards

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Move the `@config` at-rule to the top level of the stylesheet.
  2. Remove any wrapping block around `@config`.

Example fix

// before
@media (min-width: 768px) {
  @config "./tw.js";
}
// after
@config "./tw.js";
Defensive patterns

Strategy: validation

Validate before calling

function assertConfigTopLevel(ast) {
  walk(ast, (node, ctx) => {
    if (node.kind === 'at-rule' && node.name === '@config' && ctx.parent !== null) {
      throw new Error('@config must be top-level');
    }
  });
}

Prevention

When it happens

Trigger: Writing `@config "./tw.js";` inside a `@layer`, `@media`, or selector. The walker tracks nesting via `ctx.parent`.

Common situations: Indenting `@config` under another rule by accident; merging config directives during refactor and losing the top-level position.

Related errors


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