{"record":{"id":"5a8e9f03a5289921","repo":"maotoumao/MusicFree","slug":"toast-failtoshareplugin","errorCode":null,"errorMessage":"toast.failToSharePlugin","messagePattern":"toast\\.failToSharePlugin","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/pages/setting/settingTypes/pluginSetting/components/pluginItem.tsx","lineNumber":62,"sourceCode":"            async onPress() {\r\n                try {\r\n                    await pluginManager.updatePlugin(plugin);\r\n                    Toast.success(t(\"toast.pluginUpdateSuccess\"));\r\n                } catch (e: any) {\r\n                    Toast.warn(e?.message ?? t(\"toast.failToUpdatePlugin\"));\r\n                }\r\n            },\r\n            show: !!plugin.instance.srcUrl,\r\n        },\r\n        {\r\n            title: t(\"pluginSetting.pluginItem.options.sharePlugin\"),\r\n            icon: \"share\",\r\n            async onPress() {\r\n                try {\r\n                    Clipboard.setString(plugin.instance.srcUrl!);\r\n                    Toast.success(t(\"toast.copiedToClipboard\"));\r\n                } catch (e: any) {\r\n                    Toast.warn(e?.message ?? t(\"toast.failToSharePlugin\"));\r\n                }\r\n            },\r\n            show: !!plugin.instance.srcUrl,\r\n        },\r\n        {\r\n            title: t(\"pluginSetting.pluginItem.options.uninstallPlugin\"),\r\n            icon: \"trash-outline\",\r\n            show: true,\r\n            onPress() {\r\n                showDialog(\"SimpleDialog\", {\r\n                    title: t(\"pluginSetting.pluginItem.options.uninstallPlugin\"),\r\n                    content: t(\"pluginSetting.pluginItem.options.uninstallPluginContent\", {\r\n                        name: plugin.name,\r\n                    }),\r\n                    async onOk() {\r\n                        try {\r\n                            await pluginManager.uninstallPlugin(plugin.hash);\r\n                            Toast.success(t(\"toast.pluginUninstalled\"));\r","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/maotoumao/MusicFree/blob/d118b18b3d0c904400f7eea7bf99c0ceec6c1aee/src/pages/setting/settingTypes/pluginSetting/components/pluginItem.tsx#L44-L80","documentation":"This fallback toast appears when the 'Share plugin' option fails. Sharing is implemented by writing `plugin.instance.srcUrl` to the system clipboard via `Clipboard.setString(...)` from @react-native-clipboard/clipboard; any rejection (or the non-null-asserted srcUrl being unexpectedly absent) is caught and shown as 'failToSharePlugin' (preferring the error's own message).","triggerScenarios":"Tapping the share option on a plugin (option is shown when `plugin.instance.srcUrl` is truthy) and `Clipboard.setString(plugin.instance.srcUrl!)` throws — e.g. the native clipboard module is unavailable, the promise rejects on certain OEM/Android versions, or srcUrl is undefined despite the truthiness check due to a stale plugin object.","commonSituations":"Missing or mismatched native clipboard dependency (new architecture/autolinking issues after RN upgrade); Android 10+ background clipboard restrictions in unusual contexts; emulator clipboard service quirks; corrupted plugin instance where srcUrl became null after a failed state update.","solutions":["Verify @react-native-clipboard/clipboard is installed and natively linked (rebuild the app / `npx pod-install` on iOS).","Guard the srcUrl before calling the clipboard and surface a clearer message if it is missing.","Retry the copy once — transient clipboard service failures occur on some devices.","As a fallback, show the srcUrl in a dialog so the user can copy it manually."],"exampleFix":"// before\nClipboard.setString(plugin.instance.srcUrl!);\n// after\nconst url = plugin.instance.srcUrl;\nif (typeof url !== \"string\" || !url) {\n    Toast.warn(t(\"toast.failToSharePlugin\"));\n    return;\n}\nawait Clipboard.setString(url);","handlingStrategy":"validation","validationCode":"const url = plugin.instance.srcUrl;\nif (typeof url !== \"string\" || !url) {\n    Toast.warn(t(\"toast.failToSharePlugin\"));\n    return;\n}\nawait Clipboard.setString(url);","typeGuard":"function hasShareableSrcUrl(p: Plugin): boolean {\n    return typeof p.instance.srcUrl === \"string\" && p.instance.srcUrl.length > 0;\n}","tryCatchPattern":"try {\n    await Clipboard.setString(plugin.instance.srcUrl!);\n    Toast.success(t(\"toast.copiedToClipboard\"));\n} catch (e: any) {\n    Toast.warn(e?.message ?? t(\"toast.failToSharePlugin\"));\n}","preventionTips":["Never rely on a truthiness check far above the usage — re-validate srcUrl right before the clipboard call.","Keep @react-native-clipboard/clipboard linked and rebuild native code after upgrades.","Offer a manual-copy fallback dialog when clipboard writes fail.","Test clipboard operations on Android 10+ where background clipboard access is restricted."],"tags":["clipboard","react-native","plugin-share"],"backgroundTag":"clipboard-write-failed","analyzedSha":"d118b18b3d0c904400f7eea7bf99c0ceec6c1aee","analyzedAt":"2026-08-30T11:49:12.932Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}