tailwindlabs/tailwindcss · error · Error
`@source` cannot be nested.
Error message
`@source` cannot be nested.
What it means
Thrown when an `@source` at-rule is encountered with a non-null parent (`ctx.parent !== null`). Like `@utility`, `@source` is a top-level directive; nesting it under `@media`, a selector rule, or any other block is rejected immediately after the no-body check.
Source
Thrown at packages/tailwindcss/src/index.ts:264
}
}
throw new Error(
`\`@utility ${node.params}\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.`,
)
}
customUtilities.push(utility)
}
// Collect paths from `@source` at-rules
if (node.name === '@source') {
if (node.nodes.length > 0) {
throw new Error('`@source` cannot have a body.')
}
if (ctx.parent !== null) {
throw new Error('`@source` cannot be nested.')
}
let not = false
let inline = false
let path = node.params
if (path[0] === 'n' && path.startsWith('not ')) {
not = true
path = path.slice(4)
}
if (path[0] === 'i' && path.startsWith('inline(')) {
inline = true
path = path.slice(7, -1).trim()
}
if (
(path[0] === '"' && path[path.length - 1] !== '"') ||View on GitHub (pinned to 16e94cbf7f)
Solutions
- Move the `@source` statement to the top level of the stylesheet.
- Use globs to narrow scope rather than structural nesting: `@source "./theme/**/*.html"`.
- Use `@source not("...")` to exclude paths instead of wrapping in conditional rules.
Example fix
/* before */
.theme-dark {
@source "./dark/**/*.html";
}
/* after */
@source "./dark/**/*.html"; Defensive patterns
Strategy: validation
Validate before calling
// Reject nested @source the same way the library does.
import postcss from 'postcss'
function validateSourceIsTopLevel(css: string): string[] {
const errors: string[] = []
postcss.parse(css).walkAtRules('@source', (rule) => {
if (rule.parent && rule.parent.type !== 'root') {
errors.push(`@source ${rule.params} must be at the top level`)
}
})
return errors
} Prevention
- Keep `@source` directives at the top of the stylesheet, near other configuration at-rules.
- Use `@source not("...")` to exclude paths rather than wrapping in conditional blocks.
- Lint for any non-root parent of statement at-rules.
When it happens
Trigger: Placing `@source` inside `@media`, inside a selector, or inside another at-rule, e.g. `.theme { @source "./theme/**/*.html"; }`.
Common situations: Trying to scope source discovery to a sub-tree; preprocessors that wrap content; refactors that indent directives.
Related errors
- `@utility` cannot be nested.
- `@source` cannot have a body.
- `@custom-variant` cannot be nested.
- `@plugin` cannot be nested.
- `@config` cannot be nested.
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/bd15fb331a38682f.
Report an issue: GitHub.