tailwindlabs/tailwindcss · error · Error
The path given to `source(…)` must be a directory but got `s
Error message
The path given to `source(…)` must be a directory but got `source(${basePath})` instead. What it means
The Webpack plugin performs the same `source(…)` directory validation as Turbopack: it `statSync`s the resolved path and throws if the entry exists but is not a directory. `ENOENT` is swallowed, so a not-yet-created directory is allowed (useful when the dir is generated during the build).
Source
Thrown at packages/@tailwindcss-webpack/src/index.ts:248
// Skip negated patterns
if (glob.pattern[0] === '!') continue
// Avoid adding a dependency on the base directory itself
if (glob.pattern === '*' && base === glob.base) {
continue
}
this.addContextDependency(path.resolve(glob.base))
}
// Validate that source(...) paths are directories
let root = compiler.root
if (root !== 'none' && root !== null) {
let basePath = normalizePath(path.resolve(root.base, root.pattern))
try {
let stats = fs.statSync(basePath)
if (!stats.isDirectory()) {
throw new Error(
`The path given to \`source(…)\` must be a directory but got \`source(${basePath})\` instead.`,
)
}
} catch (err) {
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
throw err
}
// Directory doesn't exist yet, which is fine
}
}
DEBUG && I.end('Register dependency messages')
}
DEBUG && I.start('Build utilities')
let css = compiler.build([...context.candidates])
DEBUG && I.end('Build utilities')
// Optionally optimize the outputView on GitHub (pinned to 16e94cbf7f)
Solutions
- Use a directory path or a glob pattern whose non-glob prefix is a directory.
- If the directory is build output, ensure it is created before the webpack build, or point `@source` at the source directory instead.
- Remove any file occupying the intended directory path.
Example fix
/* before */ @source "./pages/index.html"; /* after */ @source "./pages/**/*.html";
Defensive patterns
Strategy: validation
Validate before calling
import { statSync } from 'node:fs'
function assertSourceDirOrMissing(pattern: string, base: string) {
const p = path.resolve(base, pattern)
try {
if (!statSync(p).isDirectory()) throw new Error(`source(${pattern}) is a file, not a directory`)
} catch (e) { if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e }
} Type guard
function isDirectory(p: string): boolean {
try { return statSync(p).isDirectory() } catch { return false }
} Prevention
- Point source() at directories or globs, not files.
- Ensure no file shadows an intended directory path.
- For generated dirs, create them before the webpack build.
When it happens
Trigger: `source("./dist/index.html")` where the path is a file, or any `@source` whose literal prefix resolves to an existing non-directory entry. index.ts:248 throws after `statSync` + `!isDirectory()`. (Missing paths do NOT throw.)
Common situations: Same-family mistake as the other bundler plugins: a file path used where a directory/glob is required, or a directory replaced by a same-named file.
Related errors
- The `source(${compiler.root.pattern})` does not exist or is
- The path given to `source(…)` must be a directory but got `s
- The path given to `source(…)` must be a directory but got `s
- The browser build does not support @import for "${id}"
- <stdin> has no metadata
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/02202f535e55cbce.
Report an issue: GitHub.