vitejs/vite · error · Error

Preprocessor dependency

Error message

Preprocessor dependency "${lang}" not found. Did you install it? Try `${installCommand} -D ${lang}`.

What it means

Thrown by `loadPreprocessorPath` when Vite cannot resolve a CSS preprocessor package (sass, less, stylus, styl, sugarss) from either the project root or Vite's own install directory. css.ts:2515 names the lang and suggests the install command for the detected package manager. Vite does not bundle preprocessors; they are optional peer deps the user must install.

Solutions

  1. Install the named preprocessor as a devDependency: `npm install -D sass` (or sass-embedded, less, stylus, sugarss — use the exact `lang` from the message).
  2. If in a monorepo, install at the workspace root or ensure hoisting reaches the consuming package.
  3. In CI, install with devDependencies included (`npm ci` not `npm ci --omit=dev`).
  4. If you did not intend to use the preprocessor, remove/rename the offending stylesheet extension or convert it to plain CSS.
  5. After installing, clear Vite's cache (`node_modules/.vite`) and restart.

Example fix

// before: App.vue imports <style lang="sass">
// but neither sass nor sass-embedded is installed

// after
// $ npm install -D sass-embedded
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const PREPROCESSORS = ['sass', 'sass-embedded', 'less', 'stylus', 'styl', 'sugarss']
function assertPreprocessorsInstalled(root: string, used: string[]) {
  for (const lang of used) {
    try { require.resolve(lang, { paths: [root] }) }
    catch { throw new Error(`Preprocessor '${lang}' is used but not installed. Run: npm i -D ${lang}`) }
  }
}

Type guard

function isKnownPreprocessorLang(lang: string): boolean {
  return ['sass', 'sass-embedded', 'less', 'stylus', 'styl', 'sugarss'].includes(lang)
}

Try / catch

try {
  await build()
} catch (e) {
  if (e instanceof Error && /Preprocessor dependency .* not found/.test(e.message)) {
    const lang = e.message.match(/"([^"]+)" not found/)?.[1]
    console.error(`Install the missing preprocessor: npm i -D ${lang}`)
  }
  throw e
}

Prevention

When it happens

Trigger: Source imports a `.scss`/`.sass`/`.less`/`.styl`/`.sugarss` file (or sets a matching `moduleTypes`), Vite calls `loadPreprocessorPath(lang, root)`, `nodeResolveWithVite` returns null for both root and `_dirname`, and line 2515 throws.

Common situations: Added a Sass/Less file but did not install the preprocessor. Cloned a repo and ran a partial install that omitted devDeps. Switched from sass to sass-embedded without installing it. Monorepo where the preprocessor is hoisted to a location Vite's resolver cannot reach. CI that prunes devDependencies.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/294182e5b2bf97e8. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/node/plugins/css.ts:2515

function loadPreprocessorPath(
  lang: PreprocessLang | PostCssDialectLang | 'sass-embedded',
  root: string,
): string {
  const cached = loadedPreprocessorPath[lang]
  if (cached) {
    return cached
  }

  // Try resolve from project root first, then the current vite installation path
  const resolved =
    nodeResolveWithVite(lang, undefined, { root }) ??
    nodeResolveWithVite(lang, _dirname, { root })
  if (resolved) return (loadedPreprocessorPath[lang] = resolved)

  // Error if we can't find the preprocessor
  const installCommand = getPackageManagerCommand('install')
  throw new Error(
    `Preprocessor dependency "${lang}" not found. Did you install it? Try \`${installCommand} -D ${lang}\`.`,
  )
}

function loadSassPackage(
  root: string,
  skipEmbedded = false,
): {
  name: 'sass' | 'sass-embedded'
  path: string
} {
  // try sass-embedded before sass, unless skipEmbedded is true
  if (!skipEmbedded) {
    try {
      const path = loadPreprocessorPath('sass-embedded', root)
      return { name: 'sass-embedded', path }
    } catch (e1) {
      try {

View on GitHub (pinned to b4d66fee14)