rolldown/rolldown · error · napi::Error

Missing options for ViteReactRefreshWrapperPlugin

Error message

Missing options for ViteReactRefreshWrapperPlugin

What it means

ViteReactRefreshWrapper requires its wrapper configuration; try_from returns a NAPI InvalidArg error when the plugin binding has no options, since BindingViteReactRefreshWrapperPluginConfig cannot be constructed from nothing.

Solutions

  1. Supply the options object with the React refresh wrapper config
  2. Check BindingViteReactRefreshWrapperPluginConfig for required fields (e.g. preamble code, include/exclude)
  3. Use the official Vite/rolldown React integration instead of hand-registering the plugin
  4. Ensure the plugin name matches the binding enum so options parsing happens on the right branch

Example fix

// before
builtinPlugins: [{ name: 'vite:react-refresh-wrapper' }]
// after
builtinPlugins: [{ name: 'vite:react-refresh-wrapper', options: { preambleCode: '...', include: [/\.tsx?$/] } }]
Defensive patterns

Strategy: validation

Validate before calling

const refresh = builtinPlugins.find(p => p.name === 'vite:react-refresh-wrapper');
if (refresh && !refresh.options) {
  throw new Error('vite:react-refresh-wrapper requires options (preambleCode, include/exclude)');
}

Prevention

When it happens

Trigger: Registering the ViteReactRefreshWrapper builtin plugin without options — e.g. { name: 'vite:react-refresh-wrapper' } with no config (preamble code, react refresh paths etc. missing).

Common situations: Setting up React HMR through rolldown's builtin plugin manually; the integration that normally injects the refresh wrapper options is bypassed or misconfigured.

Understand the failure class

Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.

Related errors


AI-assisted analysis of rolldown/rolldown@91b44b9d7b (2026-09-07). Data as JSON: /api/errors/dd4238fe37698b3e. Report an issue: GitHub.

Appendix: source

Thrown at crates/rolldown_binding/src/options/plugin/binding_builtin_plugin.rs:161

            napi::Status::InvalidArg,
            "Missing options for ViteManifestPlugin",
          ));
        };
        Arc::new(plugin)
      }
      BindingBuiltinPluginName::ViteModulePreloadPolyfill => {
        let plugin = if let Some(options) = plugin.options {
          BindingViteModulePreloadPolyfillPluginConfig::from_unknown(options)?.into()
        } else {
          ViteModulePreloadPolyfillPlugin::default()
        };
        Arc::new(plugin)
      }
      BindingBuiltinPluginName::ViteReactRefreshWrapper => {
        let config = if let Some(options) = plugin.options {
          BindingViteReactRefreshWrapperPluginConfig::from_unknown(options)?
        } else {
          return Err(napi::Error::new(
            napi::Status::InvalidArg,
            "Missing options for ViteReactRefreshWrapperPlugin",
          ));
        };
        Arc::new(ViteReactRefreshWrapperPlugin::new(config.into()))
      }
      BindingBuiltinPluginName::ViteReporter => {
        let plugin: ViteReporterPlugin = if let Some(options) = plugin.options {
          BindingViteReporterPluginConfig::from_unknown(options)?.into()
        } else {
          return Err(napi::Error::new(
            napi::Status::InvalidArg,
            "Missing options for ViteReporterPlugin",
          ));
        };
        Arc::new(plugin)
      }
      BindingBuiltinPluginName::ViteResolve => {

View on GitHub (pinned to 91b44b9d7b)