tailwindlabs/tailwindcss · error · Error
No `loadModule` function provided to `compile`
Error message
No `loadModule` function provided to `compile`
What it means
Thrown by `throwOnLoadModule()`, the default value for the `loadModule` option of `compile()`. The compile pipeline calls `loadModule` only when it encounters `@plugin` or `@config` directives in CSS that require loading a JS module from disk. If the integrator did not supply a `loadModule` callback, the default throws to signal that JS module resolution is unavailable in the current environment (e.g. a browser/WASM build, or a custom compile call without a filesystem).
Source
Thrown at packages/tailwindcss/src/index.ts:79
base: string,
resourceHint: 'plugin' | 'config',
) => Promise<{
path: string
base: string
module: Plugin | Config
}>
loadStylesheet?: (
id: string,
base: string,
) => Promise<{
path: string
base: string
content: string
}>
}
function throwOnLoadModule(): never {
throw new Error('No `loadModule` function provided to `compile`')
}
function throwOnLoadStylesheet(): never {
throw new Error('No `loadStylesheet` function provided to `compile`')
}
function parseThemeOptions(params: string) {
let options = ThemeOptions.NONE
let prefix = null
for (let option of segment(params, ' ')) {
if (option === 'reference') {
options |= ThemeOptions.REFERENCE
} else if (option === 'inline') {
options |= ThemeOptions.INLINE
} else if (option === 'default') {
options |= ThemeOptions.DEFAULT
} else if (option === 'static') {View on GitHub (pinned to 16e94cbf7f)
Solutions
- Remove the `@plugin` / `@config` directive from the CSS if you do not need JS plugins in this environment.
- Provide a `loadModule` callback to `compile` that resolves and imports the module (the PostCSS plugin and CLI already do this).
- If you are in a browser/edge runtime, port the plugin's behavior to CSS/`@theme` instead of a JS module.
- For v4, prefer the CSS-first config (`@theme`, `@plugin` only when you control loading) over `@config`.
Example fix
// before
import { compile } from 'tailwindcss'
// css contains: @plugin "./my-plugin.js";
let result = await compile(css)
// after
import { compile } from 'tailwindcss'
let result = await compile(css, {
loadModule: async (id, base) => {
let path = await resolve(id, base)
return { path, base, module: await import(path) }
},
}) Defensive patterns
Strategy: validation
Validate before calling
function needsLoadModule(css: string): boolean {
return /@plugin\s+|@config\s+/.test(css);
}
// Before calling compile:
if (needsLoadModule(css) && typeof options.loadModule !== 'function') {
throw new Error('CSS uses @plugin/@config but no loadModule was provided');
} Type guard
function hasLoadModule(opts: CompileOptions): opts is CompileOptions & { loadModule: NonNullable<CompileOptions['loadModule']> } {
return typeof opts.loadModule === 'function';
} Try / catch
try {
await compile(css, opts);
} catch (e) {
if (e instanceof Error && e.message === 'No `loadModule` function provided to `compile`') {
// either remove @plugin/@config or supply a loadModule
} else throw e;
} Prevention
- Avoid @plugin/@config in browser/edge builds of the compiler.
- When using the low-level compile API, always pass loadModule and loadStylesheet.
- Migrate v3 @config usage to v4 CSS-first @theme where possible.
- Use the official PostCSS plugin or CLI, which wire up module loading for you.
When it happens
Trigger: Calling `compile(css, { ... })` without a `loadModule` option while the CSS contains `@plugin "./my-plugin.js"` or `@config "./tailwind.config.js"`. The standalone `compile` export defaults `loadModule` to `throwOnLoadModule`, so any `@plugin`/`@config` triggers it. Browsers and constrained runtimes cannot load filesystem modules, hence the guard.
Common situations: Using the Tailwind v4 compiler in a browser/WASM/edge environment where `@plugin` or `@config` is present but no FS loader exists; calling the low-level `compile` API directly (instead of the PostCSS plugin or CLI which wire up `loadModule`); keeping a `@config` directive after migrating to v4.
Related errors
- `@plugin` must have a path.
- Unexpected `@plugin` option: Value of declaration `${toCss([
- The plugin "${detail.path}" does not accept options
- The --spacing(…) function requires that the `--spacing` them
- The browser build does not support plugins or config files.
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/13510cf82993d173.
Report an issue: GitHub.