{"record":{"id":"586702ff5c498a27","repo":"tauri-apps/tauri","slug":"valid-plugin","errorCode":null,"errorMessage":"valid plugin","messagePattern":"valid plugin","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri/src/plugin.rs","lineNumber":755,"sourceCode":"      setup: self.setup,\n      js_init_script: self.js_init_script,\n      on_navigation: self.on_navigation,\n      on_page_load: self.on_page_load,\n      on_window_ready: self.on_window_ready,\n      on_webview_ready: self.on_webview_ready,\n      on_event: self.on_event,\n      on_drop: self.on_drop,\n      uri_scheme_protocols: self.uri_scheme_protocols,\n    })\n  }\n\n  /// Builds the [`TauriPlugin`].\n  ///\n  /// # Panics\n  ///\n  /// If the builder returns an error during [`Self::try_build`], then this method will panic.\n  pub fn build(self) -> TauriPlugin<R, C> {\n    self.try_build().expect(\"valid plugin\")\n  }\n}\n\n/// Plugin struct that is returned by the [`Builder`]. Should only be constructed through the builder.\npub struct TauriPlugin<R: Runtime, C: DeserializeOwned = ()> {\n  name: &'static str,\n  app: Option<AppHandle<R>>,\n  invoke_handler: Box<InvokeHandler<R>>,\n  setup: Option<Box<SetupHook<R, C>>>,\n  js_init_script: Option<InitializationScript>,\n  on_navigation: Box<OnNavigation<R>>,\n  on_page_load: Box<OnPageLoad<R>>,\n  on_window_ready: Box<OnWindowReady<R>>,\n  on_webview_ready: Box<OnWebviewReady<R>>,\n  on_event: Box<OnEvent<R>>,\n  on_drop: Option<Box<OnDrop<R>>>,\n  uri_scheme_protocols: HashMap<String, Arc<UriSchemeProtocol<R>>>,\n}","sourceCodeStart":737,"sourceCodeEnd":773,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri/src/plugin.rs#L737-L773","documentation":"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'.","triggerScenarios":"tauri::plugin::Builder::new(\"core\").build() or Builder::new(\"tauri\").build() — any custom plugin constructed with one of those two names.","commonSituations":"Writing a custom plugin and naming it 'core' or 'tauri' (e.g. an internal core module exposed as a plugin).","solutions":["Rename the plugin to anything other than 'core' or 'tauri'.","For graceful handling, call try_build() and match BuilderError::ReservedName instead of build()."],"exampleFix":"// before\nlet plugin = tauri::plugin::Builder::<R>::new(\"core\").build();\n\n// after\nlet plugin = tauri::plugin::Builder::<R>::new(\"app-core\").build();\n// or: match builder.try_build() { Ok(p) => p, Err(e) => /* handle */ }","handlingStrategy":"try-catch","validationCode":"assert!(!matches!(name, \"core\" | \"tauri\"), \"plugin name '{name}' is reserved\");","typeGuard":"fn is_valid_plugin_name(name: &str) -> bool {\n    !matches!(name, \"core\" | \"tauri\")\n}","tryCatchPattern":"match tauri::plugin::Builder::<R>::new(name).try_build() {\n    Ok(plugin) => plugin,\n    Err(tauri::plugin::BuilderError::ReservedName(n)) => {\n        // rename or surface a configuration error\n        return Err(format!(\"plugin name '{n}' is reserved\"));\n    }\n    Err(e) => return Err(e.to_string()),\n}","preventionTips":["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."],"tags":["tauri","plugin","reserved-name","builder"],"backgroundTag":"reserved-name-conflict","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","contentChangedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}