{"record":{"id":"69d928313a0a2c5b","repo":"tailwindlabs/tailwindcss","slug":"the-path-given-to-source-must-be-a-directory-69d928","errorCode":null,"errorMessage":"The path given to `source(…)` must be a directory but got `source(${basePath})` instead.","messagePattern":"The path given to `source\\(…\\)` must be a directory but got `source\\((.+?)\\)` instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@tailwindcss-vite/src/index.ts","lineNumber":667,"sourceCode":"        }\n        // Ensure relative is a posix style path since we will merge it with the\n        // glob.\n        relative = normalizePath(relative)\n\n        addWatchFile(path.posix.join(relative, glob.pattern))\n\n        let root = this.compiler.root\n\n        if (root !== 'none' && root !== null) {\n          let basePath = normalizePath(path.resolve(root.base, root.pattern))\n\n          let isDir = await fs.stat(basePath).then(\n            (stats) => stats.isDirectory(),\n            () => false,\n          )\n\n          if (!isDir) {\n            throw new Error(\n              `The path given to \\`source(…)\\` must be a directory but got \\`source(${basePath})\\` instead.`,\n            )\n          }\n        }\n      }\n      DEBUG && I.end('Register dependency messages')\n    }\n\n    DEBUG && I.start('Build CSS')\n    let code = this.compiler.build([...this.candidates])\n    DEBUG && I.end('Build CSS')\n\n    DEBUG && I.start('Build Source Map')\n    let map = this.enableSourceMaps ? toSourceMap(this.compiler.buildSourceMap()).raw : undefined\n    DEBUG && I.end('Build Source Map')\n\n    return {\n      code,","sourceCodeStart":649,"sourceCodeEnd":685,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/@tailwindcss-vite/src/index.ts#L649-L685","documentation":"The Vite plugin validates each `source(…)` path resolves to a directory. It stats `basePath` and, if the stat either fails or the entry is not a directory, throws. Unlike the Turbopack/Webpack variants, the Vite version treats both not-found and not-a-directory as failure (`isDir` is false on rejection).","triggerScenarios":"`source(\"./src/index.html\")` pointing at a file, or `source(\"./does-not-exist\")`. `fs.stat(basePath)` rejects or returns a non-directory, `isDir` is false, and index.ts:667 throws.","commonSituations":"Pointing `@source` at a file instead of a directory/glob, a source directory deleted during dev, or a path that is only present after a generate step that hasn't run.","solutions":["Point `source(…)` at a directory or use a glob whose literal prefix is a directory.","Ensure the directory exists at build/dev start time (create it or order your scripts so generators run first).","Avoid pointing `@source` at individual files."],"exampleFix":"/* before */\n@source \"./src/main.tsx\";\n\n/* after */\n@source \"./src/**/*.{ts,tsx}\";","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises'\nasync function assertSourceDir(pattern: string, base: string) {\n  const p = path.resolve(base, pattern)\n  const isDir = await stat(p).then(s => s.isDirectory()).catch(() => false)\n  if (!isDir) throw new Error(`source(${pattern}) must resolve to an existing directory: ${p}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await build()\n} catch (e) {\n  if (/source\\(.*\\) must be a directory/.test((e as Error).message)) {\n    // point source() at a directory or fix the glob\n  }\n  throw e\n}","preventionTips":["Use directory paths or globs in source(); never bare files.","Ensure source directories exist at dev/build start.","Order build scripts so generated dirs exist before Vite runs."],"tags":["vite","source-detection","filesystem"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}