{"record":{"id":"dc718e026544726c","repo":"Molunerfinn/PicGo","slug":"import-local-plugin-failed","errorCode":null,"errorMessage":"Import local plugin failed","messagePattern":"Import local plugin failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/renderer/store/plugins/actions.ts","lineNumber":388,"sourceCode":"        status: content.trim() ? pluginReadmeStatus.Ready : pluginReadmeStatus.Empty,\n        content,\n        errorMessage: null\n      })\n    } catch (error) {\n      pluginStoreActions.setReadmeState(fullName, {\n        status: pluginReadmeStatus.Error,\n        content: '',\n        errorMessage: error instanceof Error ? error.message : String(error)\n      })\n    }\n  },\n  async importLocalPlugin (): Promise<PluginImportResult | null> {\n    pluginStoreActions.setImportingLocal(true)\n\n    try {\n      const result = await pluginsAdapter.importLocalPlugin()\n      if (!result.success) {\n        throw new Error(result.error || 'Import local plugin failed')\n      }\n\n      if (!result.data) {\n        return null\n      }\n\n      await appActions.hydrateAppState()\n      const installedPlugins = await pluginsAdapter.getInstalledPlugins()\n      pluginStoreActions.setInstalledPlugins(installedPlugins.map(mapInstalledPluginItem))\n      const installedPlugin = useAppStore.getState().pluginsInstalled.find(\n        (item) => item.fullName === result.data || item.name === result.data\n      )\n\n      if (!installedPlugin) {\n        throw new Error('Imported plugin not found')\n      }\n\n      toast.success(i18n.t('PLUGIN_IMPORT_SUCCEED'))","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/Molunerfinn/PicGo/blob/07ec7068a5512344da093d49a8408fa63ba3421e/src/renderer/store/plugins/actions.ts#L370-L406","documentation":"importLocalPlugin delegates to pluginsAdapter.importLocalPlugin() (IPC into the main process) and throws this error when the adapter result reports success:false. The literal message is a fallback used when result.error is empty, meaning the main process failed without returning a specific reason. The action sets importingLocal(true) first and clears it in the finally path.","triggerScenarios":"Calling importLocalPlugin() when the main-process import fails: the selected file cannot be read, the npm package is malformed (no package.json/main), the plugin directory is not a valid PicGo plugin, or the adapter resolves with { success: false, error: undefined }.","commonSituations":"User picks a wrong file type in the import dialog; plugin bundle was built for a different Node/Electron ABI; permission errors reading the plugin path; installing from a corrupted or partially extracted archive.","solutions":["Catch the error and surface result.error text if available; prefer errors returned by the adapter over the fallback message.","Verify the selected path is a valid PicGo plugin directory containing package.json with a matching main entry.","Rebuild/reinstall the local plugin so it matches the app's Node/Electron version.","Check file read permissions on the plugin path and retry the import."],"exampleFix":"// before\nconst imported = await pluginStoreActions.importLocalPlugin()\n\n// after\ntry {\n  const imported = await pluginStoreActions.importLocalPlugin()\n} catch (err) {\n  toast.error((err as Error).message)\n} finally {\n  pluginStoreActions.setImportingLocal(false)\n}","handlingStrategy":"try-catch","validationCode":"// pre-check the chosen path is a plugin-like directory before import\nconst isPluginDir = await window.db.confirm({\n  title: i18n.t('PLUGIN_IMPORT_CONFIRM')\n})\nif (!isPluginDir) return","typeGuard":"function isFailedImport(\n  result: PluginImportResult\n): result is { success: false; error?: string } {\n  return result.success === false\n}","tryCatchPattern":"try {\n  const imported = await pluginStoreActions.importLocalPlugin()\n} catch (err) {\n  toast.error(i18n.t('PLUGIN_IMPORT_FAILED') + ': ' + (err as Error).message)\n}","preventionTips":["Prefer importing packed, valid plugin packages (with package.json and main entry).","Match the plugin build target to the app's Electron/Node ABI.","Surface result.error from the adapter instead of relying on the generic fallback message.","Keep the importingLocal flag reset in finally so a failed import does not block retries."],"tags":["plugin","import","ipc","filesystem"],"backgroundTag":"plugin-import-failed","analyzedSha":"07ec7068a5512344da093d49a8408fa63ba3421e","analyzedAt":"2026-08-30T01:45:22.289Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}