vitejs/vite · error · Error

Failed to load PostCSS config: ${e}

Error message

Failed to load PostCSS config: ${e}

What it means

Thrown when loading the PostCSS configuration fails for a reason other than 'no config found'. Vite runs `postcssrc()` to discover `postcss.config.js`; if the file exists but throws (syntax error, a referenced plugin not installed, an invalid export), the original error is re-thrown with a wrapper message identifying the search path.

Source

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

    delete options.plugins
    result = {
      options,
      plugins: inlineOptions.plugins || [],
    }
  } else {
    const searchPath =
      typeof inlineOptions === 'string' ? inlineOptions : config.root
    const stopDir = searchForWorkspaceRoot(config.root)
    result = postcssrc({}, searchPath, { stopDir }).catch((e) => {
      if (!e.message.includes('No PostCSS Config found')) {
        if (e instanceof Error) {
          const { name, message, stack } = e
          e.name = 'Failed to load PostCSS config'
          e.message = `Failed to load PostCSS config (searchPath: ${searchPath}): [${name}] ${message}\n${stack}`
          e.stack = '' // add stack to message to retain stack
          throw e
        } else {
          throw new Error(`Failed to load PostCSS config: ${e}`)
        }
      }
      return null
    })
    // replace cached promise to result object when finished
    result.then(
      (resolved) => {
        postcssConfigCache.set(config, resolved)
      },
      () => {
        /* keep as rejected promise, will be handled later */
      },
    )
  }

  postcssConfigCache.set(config, result)
  return result
}

View on GitHub (pinned to 89620f09af)

Solutions

  1. Install the missing PostCSS plugin(s) named in the underlying error (`npm i -D tailwindcss autoprefixer`).
  2. Fix any syntax/require errors in `postcss.config.js` / `.postcssrc.js`.
  3. Ensure the config format matches your project's module system (`module.exports` for CJS, `export default` for ESM).
  4. Temporarily rename the PostCSS config to confirm it is the culprit, then fix incrementally.

Example fix

// before — postcss.config.js references uninstalled plugin
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } };
// after — install and validate
// npm i -D tailwindcss autoprefixer
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } };
Defensive patterns

Strategy: try-catch

Validate before calling

import { existsSync, readFileSync } from 'node:fs';
import { pathToFileURL } from 'node:url';

async function validatePostcssConfig(file) {
  if (!existsSync(file)) return;
  // attempt to import it to surface syntax/missing-plugin errors early
  await import(pathToFileURL(file).href);
}
// await validatePostcssConfig('postcss.config.js');

Try / catch

try {
  await build();
} catch (e) {
  if (/Failed to load PostCSS config/.test(e.message)) {
    console.error('Check postcss.config.js plugins are installed:', e.cause ?? e);
  }
  throw e;
}

Prevention

When it happens

Trigger: `postcssrc({}, searchPath, { stopDir })` rejects with an error whose message does not include 'No PostCSS Config found' — e.g. the config file has a syntax error, imports a missing module, or a PostCSS plugin constructor throws.

Common situations: A `postcss.config.js` with `module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } }` where `tailwindcss`/`autoprefixer` is not installed; a config written for ESM in a CJS project (or vice versa); a typo in the config; a plugin that throws on invalid options.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/d27392b13c600a17.json. Report an issue: GitHub.