tauri-apps/tauri · error
valid plugin
Error message
valid plugin
What it means
Plugin Builder::build() calls try_build(), which currently fails only when the plugin name is reserved: RESERVED_PLUGIN_NAMES = ["core", "tauri"] (crates/tauri/src/plugin.rs:191). Those names belong to Tauri's own namespace, so building a plugin with one panics with 'valid plugin'.
Source
Thrown at crates/tauri/src/plugin.rs:755
setup: self.setup,
js_init_script: self.js_init_script,
on_navigation: self.on_navigation,
on_page_load: self.on_page_load,
on_window_ready: self.on_window_ready,
on_webview_ready: self.on_webview_ready,
on_event: self.on_event,
on_drop: self.on_drop,
uri_scheme_protocols: self.uri_scheme_protocols,
})
}
/// Builds the [`TauriPlugin`].
///
/// # Panics
///
/// If the builder returns an error during [`Self::try_build`], then this method will panic.
pub fn build(self) -> TauriPlugin<R, C> {
self.try_build().expect("valid plugin")
}
}
/// Plugin struct that is returned by the [`Builder`]. Should only be constructed through the builder.
pub struct TauriPlugin<R: Runtime, C: DeserializeOwned = ()> {
name: &'static str,
app: Option<AppHandle<R>>,
invoke_handler: Box<InvokeHandler<R>>,
setup: Option<Box<SetupHook<R, C>>>,
js_init_script: Option<InitializationScript>,
on_navigation: Box<OnNavigation<R>>,
on_page_load: Box<OnPageLoad<R>>,
on_window_ready: Box<OnWindowReady<R>>,
on_webview_ready: Box<OnWebviewReady<R>>,
on_event: Box<OnEvent<R>>,
on_drop: Option<Box<OnDrop<R>>>,
uri_scheme_protocols: HashMap<String, Arc<UriSchemeProtocol<R>>>,
}View on GitHub (pinned to 52e4b6e71d)
Solutions
- Rename the plugin to anything other than 'core' or 'tauri'.
- For graceful handling, call try_build() and match BuilderError::ReservedName instead of build().
Example fix
// before
let plugin = tauri::plugin::Builder::<R>::new("core").build();
// after
let plugin = tauri::plugin::Builder::<R>::new("app-core").build();
// or: match builder.try_build() { Ok(p) => p, Err(e) => /* handle */ } Defensive patterns
Strategy: try-catch
Validate before calling
assert!(!matches!(name, "core" | "tauri"), "plugin name '{name}' is reserved"); Type guard
fn is_valid_plugin_name(name: &str) -> bool {
!matches!(name, "core" | "tauri")
} Try / catch
match tauri::plugin::Builder::<R>::new(name).try_build() {
Ok(plugin) => plugin,
Err(tauri::plugin::BuilderError::ReservedName(n)) => {
// rename or surface a configuration error
return Err(format!("plugin name '{n}' is reserved"));
}
Err(e) => return Err(e.to_string()),
} Prevention
- Avoid 'core' and 'tauri' as plugin names.
- Prefer try_build() over build() for user-supplied plugin names.
- Add a startup config check when plugin names come from config.
When it happens
Trigger: tauri::plugin::Builder::new("core").build() or Builder::new("tauri").build() — any custom plugin constructed with one of those two names.
Common situations: Writing a custom plugin and naming it 'core' or 'tauri' (e.g. an internal core module exposed as a plugin).
Related errors
- failed to canonicalize global API script path
- failed to write global API script
- Library from {} does not include required runtime symbols. T
- Android folder already exists
- iOS folder already exists
AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20).
Data as JSON: /api/errors/586702ff5c498a27.
Report an issue: GitHub.