{"record":{"id":"7112d82508870658","repo":"swc-project/swc","slug":"fallback-bindings-does-not-support-legacy-plugins","errorCode":null,"errorMessage":"Fallback bindings does not support legacy plugins, it'll be ignored.","messagePattern":"Fallback bindings does not support legacy plugins, it'll be ignored\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/core/src/index.ts","lineNumber":329,"sourceCode":"                            src,\n                            options?.jsc?.parser,\n                            options.filename\n                        )\n                        : src;\n                return this.transform(\n                    copyProgramSourceContext(m, plugin(m)),\n                    newOptions\n                );\n            }\n\n            return bindings.transform(\n                isModule ? stringifyProgram(src) : src,\n                isModule,\n                toBuffer(newOptions)\n            );\n        } else if (fallbackBindings) {\n            if (plugin && !this.fallbackBindingsPluginWarningDisplayed) {\n                console.warn(\n                    `Fallback bindings does not support legacy plugins, it'll be ignored.`\n                );\n                this.fallbackBindingsPluginWarningDisplayed = true;\n            }\n\n            return fallbackBindings.transform(src, options);\n        }\n\n        throw new Error(\"Bindings not found.\");\n    }\n\n    transformSync(src: string | Program, options?: Options): Output {\n        const isModule = typeof src !== \"string\";\n        options = options || {};\n\n        if (options?.jsc?.parser) {\n            options.jsc.parser.syntax =\n                options.jsc.parser.syntax ?? \"ecmascript\";","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/packages/core/src/index.ts#L311-L347","documentation":"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.","triggerScenarios":"await compiler.transform(src, { plugin: (m) => { ...; return m; }, ... }) while the native @swc/core binary is unavailable and the @swc/wasm fallback is in use.","commonSituations":"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.","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."],"exampleFix":"// before: plugin silently ignored on wasm fallback\nconst out = await compiler.transform(src, { plugin: myPlugin, ...opts });\n\n// after: fail fast when the plugin cannot run\nimport * as os from 'os';\nfunction assertNativeForPlugin(plugin: unknown) {\n  if (!plugin) return;\n  const { optionalDependencies } = require('@swc/core/package.json');\n  const tri = `@swc/core-${os.platform()}-${os.arch()}`;\n  const native = Object.keys(optionalDependencies).some(\n    (d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()\n  );\n  if (!native) throw new Error('SWC plugin requires native bindings; @swc/wasm fallback ignores plugins');\n}\nassertNativeForPlugin(myPlugin);\nconst out = await compiler.transform(src, { plugin: myPlugin, ...opts });","handlingStrategy":"validation","validationCode":"// Detect the wasm fallback before passing a plugin the wrapper will ignore.\nimport * as os from 'os';\nfunction nativeBindingResolves(): boolean {\n  try {\n    const { optionalDependencies } = require('@swc/core/package.json');\n    const tri = `@swc/core-${os.platform()}-${os.arch()}`;\n    return Object.keys(optionalDependencies ?? {}).some(\n      (d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()\n    );\n  } catch {\n    return false;\n  }\n}\nfunction assertPluginsRunnable(plugin: unknown): void {\n  if (plugin && !nativeBindingResolves()) {\n    throw new Error('@swc/wasm fallback cannot run legacy plugins; fix the native binding or drop the plugin option');\n  }\n}","typeGuard":"function hasNativeBindings(): boolean {\n  const os = require('os');\n  const { optionalDependencies } = require('@swc/core/package.json');\n  const tri = `@swc/core-${os.platform()}-${os.arch()}`;\n  return Object.keys(optionalDependencies ?? {}).some(\n    (d) => d.startsWith(tri) && (() => { try { require.resolve(d); return true; } catch { return false; } })()\n  );\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["wasm","plugin","fallback","swc-core","node"],"backgroundTag":"wasm-plugin-unsupported","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}