Fix: TypeError: Invalid PostCSS Plugin found at: plugins[0]
A postcss.config.js that lists plugin names as plain strings compiles nothing — the array syntax needs each entry already resolved, not a package name.
TL;DR#
A postcss.config.js whose plugins is an array of plain strings
("postcss-import", "tailwindcss", "autoprefixer") throws before any
CSS is touched, as long as that file is read by postcss-load-config —
the loader used by the standalone postcss CLI, Vite, webpack and
Storybook. In array form, postcss-load-config uses each entry exactly as
written; it does not resolve package names for you. The fix is to
require() each entry yourself, or switch to the object-keyed syntax, which
postcss-load-config resolves internally. Next.js reads postcss.config.js
with a different, internal mechanism that works the opposite way — see the
dedicated section below if that is your stack.
TypeError: Invalid PostCSS Plugin found at: plugins[0]
(@/app/postcss.config.js)
at /app/node_modules/postcss-load-config/src/plugins.js:77:15
at Array.forEach (<anonymous>)
at plugins (/app/node_modules/postcss-load-config/src/plugins.js:58:13)
at processResult (/app/node_modules/postcss-load-config/src/index.js:38:14)
at /app/node_modules/postcss-load-config/src/index.js:168:14
at async Promise.all (index 0)Why it happens#
This is the error behind a 13-vote Stack Overflow question with 24,762
views:
a developer cloned Tailwind's own setup-examples repository, edited
tailwind.config.js, then ran postcss css/tailwind.css -o generated.css
directly with the standalone postcss CLI — no Next.js, no bundler. The
build never got as far as reading the CSS file — it failed while PostCSS
was still loading its own config.
A minimal version of the broken config looks like this:
module.exports = {
plugins: [
"postcss-import",
"tailwindcss",
"autoprefixer",
]
};Reproduced in a node:20-alpine container (Node 20.20.2), with postcss@8,
postcss-cli@10 (which installed postcss-load-config@4.0.2),
tailwindcss@3 and autoprefixer@10, 17 October 2026: running npx postcss css/tailwind.css -o generated.css against the config above throws the exact
TypeError: Invalid PostCSS Plugin found at: plugins[0] above, pointing at
postcss-load-config/src/plugins.js.
Reading that file directly (it ships inside node_modules) shows the
mechanism in full. For an array plugins, the loader only filters out falsy
entries — config.plugins.filter(Boolean) — it never calls require() on
anything. It then walks the resulting list and, for each entry, throws
unless that entry is already a function, or an object with a postcssPlugin
property, or an object whose own plugins is an array:
if (
!(
(typeof plugin === 'object' && Array.isArray(plugin.plugins)) ||
(typeof plugin === 'object' && plugin.postcssPlugin) ||
(typeof plugin === 'function')
)
) {
throw new TypeError(`Invalid PostCSS Plugin found at: plugins[${i}]\n\n(@${file})`)
}For an object plugins, the same file does the opposite: it calls
Object.keys(config.plugins) and require()s each key through an internal
load() helper before running that same check — which is why the object
syntax resolves package names and the array syntax does not. The current
release on the npm registry, postcss-load-config@6.0.1 (checked 17 October
2026), still has the identical array-vs-object split in its own
src/plugins.js — this is not a defect fixed in a later version.
The traceback also shows how far the loader gets: it fails inside
processResult, before Promise.all resolves a config object, so nothing
downstream — including Tailwind's own class scanning — ever runs.
Reproducing the same config with only the first entry fixed (require() on
postcss-import, the other two still bare strings) confirms the loader
stops at the first bad entry rather than collecting every broken one: the
error becomes TypeError: Invalid PostCSS Plugin found at: plugins[1],
matching the position of the next string in the array. Fixing one entry at
a time and re-running tells you exactly which index is still wrong.
Fix#
1. Require each plugin by hand, if you keep the array syntax. This
applies to the standalone postcss CLI, Vite, webpack and Storybook — any
tool whose config is read by postcss-load-config.
module.exports = {
plugins: [
require("postcss-import"),
require("tailwindcss"),
require("autoprefixer"),
]
};2. Or switch to the object syntax, which npx tailwindcss init -p
generates by default (reproduced in the same container: a clean
tailwindcss@3 + postcss + autoprefixer install, then npx tailwindcss init -p, wrote exactly this file):
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}npx tailwindcss init -p does not add postcss-import on its own — if your
build also needs it (as the broken example above does), add it as its own
key by hand: "postcss-import": {}.
3. Re-run the build.
npx postcss css/tailwind.css -o generated.cssBoth fixes were reproduced against the same broken input: the require()
array and the object syntax each produced a generated.css with Tailwind's
base layer compiled in and exit code 0. The object syntax is not a
workaround — src/plugins.js takes a genuinely different branch for it,
the one that calls require() internally, which is also why reordering the
array entries does not help: the check in the code above runs on every
entry regardless of position.
Next.js is a different case — do not use this fix there#
If your project builds with Next.js's own CSS support (no custom bundler
reading the file), do not add require() calls. Next.js's official
PostCSS guide reads
postcss.config.js itself — it does not go through postcss-load-config —
and documents the opposite rule:
Do not use
require()to import the PostCSS Plugins. Plugins must be provided as strings.
The same page adds that if your postcss.config.js must also support
"other non-Next.js tools in the same project" (its own example is adding a
tool like Storybook, which does read the file with postcss-load-config), you
switch to the same object-keyed format shown above — because that format is
the one shape both readers accept. In other words: a bare string works
inside Next.js's own CSS pipeline by design, and only breaks once something
else (postcss-load-config, via a CLI, Vite, webpack or Storybook) reads the
same file. If your traceback names postcss-load-config/src/plugins.js,
you are not inside Next.js's own PostCSS reader when the error happens —
either you ran a standalone tool against the file, or another part of your
toolchain (Storybook, Vite, a lint step) is loading it independently.
Verify the fix#
npx postcss css/tailwind.css -o generated.css
echo $?A clean run prints only Tailwind's own No utility classes were detected
warning (if your content globs do not yet match any file) and exits 0.
In this reproduction, that run wrote a 501-line generated.css starting
with Tailwind's universal reset (*, ::before, ::after { --tw-border-spacing-x: 0; … }),
confirming the pipeline reached PostCSS, ran postcss-import and
tailwindcss, and wrote real output — not just that the process exited
without an error.
Any remaining TypeError: Invalid PostCSS Plugin found at: plugins[N] means
another entry in the array is still a bare string — fix them one at a time,
since this error always reports a single index, not every broken entry at
once. If the build runs through a bundler rather than the postcss CLI
directly, run whatever script invokes PostCSS in your project (npm run build, or the dev server) and check whether the stack names
postcss-load-config/src/plugins.js. A Next.js build that throws this same
message is loading the config through something other than Next.js's own
reader (see the section above) — the text of the error alone does not tell
you which reader is involved.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
A related but different cause: autoprefixer and PostCSS 8#
The same Stack Overflow thread's third-highest answer (score 5), posted on
the same question, warns about a separate trap: installing autoprefixer@10
moved postcss to a peer dependency and required PostCSS 8, breaking setups
still pinned to PostCSS 7. Its symptom is a different message,
Error: PostCSS plugin autoprefixer requires PostCSS 8,
not the plugins[N] TypeError this article covers — if your traceback
names autoprefixer directly instead of postcss-load-config/src/plugins.js,
that second thread is the one to follow, and the fix is to align your
postcss and autoprefixer major versions, not to change the shape of the
plugins array.
If you are on Next.js, the plugin shape is already correct, and Tailwind
classes still render nothing, that is a separate issue again: see
Tailwindcss not working with Next.js: fix the
config —
in that case PostCSS compiles without error, but Tailwind's content globs
never match your component files.
Readers on Tailwind CSS v4 who hit a plugin error with this same
postcss.config.js shape are usually facing a different, newer issue: v4
moved the PostCSS integration to a separate @tailwindcss/postcss package,
and using the old tailwindcss plugin directly throws its own error. That
case, including the Vite-specific instructions, is covered in Fix: Tailwind
PostCSS Plugin Has Moved (Vite +
React). If instead a clean
npm install on an unpinned tailwindcss dependency is what broke your
build, start from Fix "Missing specifier" & npx tailwindcss init
Errors,
which reproduces that failure one step at a time.
Either way, check which reader loads your postcss.config.js before
picking a fix: postcss-load-config (the CLI, Vite, webpack, Storybook) wants
already-resolved plugins in array form, or package names in object form;
Next.js's own reader wants string names either way, and never a
require() call.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Continue Reading
Tailwindcss not working with Next.js: fix the config
A Next.js build that finishes clean but ships a page with zero Tailwind styling almost always has one wrong setting: the paths Tailwind scans for class names.
Fix "Cannot apply unknown utility class border-border"
Reproduced on Tailwind 4.1.4 to 4.3.3 and 3.4.19: the four wordings of this error, the @config path that resolves, the hsl() trap in @theme, and the two v3 causes.
Fix: Tailwind PostCSS Plugin Has Moved (Vite + React)
The exact steps to resolve the Tailwind v4 PostCSS plugin relocation error in a Vite + React + TypeScript build.


