swc-project/swc · warning
Fallback bindings does not support legacy plugins, it'll be
Error message
Fallback bindings does not support legacy plugins, it'll be ignored.
What it means
Warning from @swc/core's JS wrapper: the native binding did not load, so transforms run on fallbackBindings (@swc/wasm), which cannot execute the legacy JS `plugin` option (the (program) => Program hook). The plugin is ignored and the warning prints once per Compiler instance, so output silently lacks the plugin's transformations.
Source
Thrown at packages/core/src/index.ts:329
src,
options?.jsc?.parser,
options.filename
)
: src;
return this.transform(
copyProgramSourceContext(m, plugin(m)),
newOptions
);
}
return bindings.transform(
isModule ? stringifyProgram(src) : src,
isModule,
toBuffer(newOptions)
);
} else if (fallbackBindings) {
if (plugin && !this.fallbackBindingsPluginWarningDisplayed) {
console.warn(
`Fallback bindings does not support legacy plugins, it'll be ignored.`
);
this.fallbackBindingsPluginWarningDisplayed = true;
}
return fallbackBindings.transform(src, options);
}
throw new Error("Bindings not found.");
}
transformSync(src: string | Program, options?: Options): Output {
const isModule = typeof src !== "string";
options = options || {};
if (options?.jsc?.parser) {
options.jsc.parser.syntax =
options.jsc.parser.syntax ?? "ecmascript";View on GitHub (pinned to 5176682b65)
Solutions
- Repair the native binding installation (npm install --include=optional, correct platform package) so the plugin path runs.
- Detect the fallback and fail fast instead of silently skipping the plugin (throw your own error when a plugin is requested).
- Move the transformation into config-driven passes that @swc/wasm supports if you must stay on wasm.
- Assert on output in tests so a skipped plugin is caught before shipping.
Example fix
// before: plugin silently ignored on wasm fallback
const out = await compiler.transform(src, { plugin: myPlugin, ...opts });
// after: fail fast when the plugin cannot run
import * as os from 'os';
function assertNativeForPlugin(plugin: unknown) {
if (!plugin) return;
const { optionalDependencies } = require('@swc/core/package.json');
const tri = `@swc/core-${os.platform()}-${os.arch()}`;
const native = Object.keys(optionalDependencies).some(
(d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()
);
if (!native) throw new Error('SWC plugin requires native bindings; @swc/wasm fallback ignores plugins');
}
assertNativeForPlugin(myPlugin);
const out = await compiler.transform(src, { plugin: myPlugin, ...opts }); Defensive patterns
Strategy: validation
Validate before calling
// Detect the wasm fallback before passing a plugin the wrapper will ignore.
import * as os from 'os';
function nativeBindingResolves(): boolean {
try {
const { optionalDependencies } = require('@swc/core/package.json');
const tri = `@swc/core-${os.platform()}-${os.arch()}`;
return Object.keys(optionalDependencies ?? {}).some(
(d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()
);
} catch {
return false;
}
}
function assertPluginsRunnable(plugin: unknown): void {
if (plugin && !nativeBindingResolves()) {
throw new Error('@swc/wasm fallback cannot run legacy plugins; fix the native binding or drop the plugin option');
}
} Type guard
function hasNativeBindings(): boolean {
const os = require('os');
const { optionalDependencies } = require('@swc/core/package.json');
const tri = `@swc/core-${os.platform()}-${os.arch()}`;
return Object.keys(optionalDependencies ?? {}).some(
(d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()
);
} Prevention
- Fail fast in your wrapper when a plugin is requested and only fallbackBindings are present.
- Verify the platform optional dependency installs in CI (npm ls @swc/core-linux-x64-gnu style checks).
- Snapshot transformed output so a silently ignored plugin breaks tests.
When it happens
Trigger: await compiler.transform(src, { plugin: (m) => { ...; return m; }, ... }) while the native @swc/core binary is unavailable and the @swc/wasm fallback is in use.
Common situations: Native install failed (missing optional dep, unsupported arch) but code still passes a plugin; browser/electron setups relying on wasm; teams not noticing output differences because only a console.warn fires.
Related errors
- Should able to be deserialized into string
- Should be serializable
- Should be serializable
- Should able to deserialize
- Should be serializable
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/7112d82508870658.
Report an issue: GitHub.