{"record":{"id":"4656995fa09ca67d","repo":"Molunerfinn/PicGo","slug":"failed-to-read-local-plugin-readme","errorCode":null,"errorMessage":"Failed to read local plugin readme","messagePattern":"Failed to read local plugin readme","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/renderer/adapters/plugins.ts","lineNumber":109,"sourceCode":"  },\n  async saveTransformer (transformer: string) {\n    await saveConfig({\n      'picBed.transformer': transformer\n    })\n  },\n  async fetchPluginReadme (fullName: string, options?: { installed?: boolean }) {\n    // For installed plugins (including locally imported ones not on npm),\n    // read README from disk via the main process — jsdelivr 404s on\n    // unpublished plugins. Non-installed plugins (e.g. search results) fall\n    // back to the CDN.\n    if (options?.installed) {\n      const result = await invokeRPC<string>(\n        IRPCActionType.GET_INSTALLED_PLUGIN_README,\n        fullName\n      )\n\n      if (!result.success) {\n        throw new Error(result.error || 'Failed to read local plugin readme')\n      }\n\n      return result.data ?? ''\n    }\n\n    let lastError: unknown = null\n\n    for (const readmeFileName of README_FILE_CANDIDATES) {\n      try {\n        const response = await axios.get<string>(\n          `https://cdn.jsdelivr.net/npm/${fullName}/${readmeFileName}`,\n          {\n            responseType: 'text'\n          }\n        )\n\n        return response.data || ''\n      } catch (error) {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/Molunerfinn/PicGo/blob/07ec7068a5512344da093d49a8408fa63ba3421e/src/renderer/adapters/plugins.ts#L91-L127","documentation":"fetchPluginReadme calls the GET_INSTALLED_PLUGIN_README RPC; if the response envelope has success:false it throws 'Failed to read local plugin readme' (or result.error if the main process supplied one). The main side could not read the plugin's README file, typically because the plugin directory or readme is missing.","triggerScenarios":"Requesting the readme for a fullName whose installed plugin folder lacks README.md (or is unreadable), or when the RPC handler fails and returns success:false with no error message.","commonSituations":"Plugin installed from a package without a README; plugin folder partially deleted or corrupted node_modules; permission issues on the plugin directory; requesting a plugin that was uninstalled in another window.","solutions":["Check result.error/logs for the main-process read failure path (ENOENT vs permissions)","Reinstall the plugin to restore its README and directory contents","Verify the plugin's install path exists and README.md is readable","Fall back to the npm registry readme for the package when the local file is absent"],"exampleFix":"// before\nconst readme = await fetchPluginReadme(fullName) // throws if local README missing\n// after\nlet readme = ''\ntry {\n  readme = await fetchPluginReadme(fullName)\n} catch {\n  readme = await fetchReadmeFromNpm(fullName)\n}","handlingStrategy":"fallback","validationCode":"const readmePath = path.join(pluginDir(fullName), 'README.md')\nif (!(await fs.pathExists(readmePath))) {\n  return fetchReadmeFromNpm(fullName)\n}","typeGuard":null,"tryCatchPattern":"try {\n  readme = await fetchPluginReadme(fullName)\n} catch {\n  readme = await fetchReadmeFromNpm(fullName).catch(() => '')\n}","preventionTips":["Render an empty/readme-missing state instead of failing the panel","Verify the plugin directory and README exist after install","Prefer the npm registry readme as a source of truth for published packages"],"tags":["plugin","readme","rpc","file-not-found"],"backgroundTag":"plugin-readme-unavailable","analyzedSha":"07ec7068a5512344da093d49a8408fa63ba3421e","analyzedAt":"2026-08-30T01:45:22.289Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}