{"record":{"id":"ca57f397c092224a","repo":"maotoumao/MusicFree","slug":"error-ca57f3","errorCode":null,"errorMessage":"无法打开链接","messagePattern":"无法打开链接","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/utils/openUrl.ts","lineNumber":9,"sourceCode":"import { Linking } from \"react-native\";\nimport Toast from \"./toast\";\n\nexport default async function (url: string) {\n    try {\n        await Linking.canOpenURL(url);\n        return Linking.openURL(url);\n    } catch {\n        Toast.warn(\"无法打开链接\");\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":12,"githubUrl":"https://github.com/maotoumao/MusicFree/blob/d118b18b3d0c904400f7eea7bf99c0ceec6c1aee/src/utils/openUrl.ts#L1-L12","documentation":"The openUrl utility wraps React Native's `Linking.canOpenURL`/`Linking.openURL`. When either call rejects — most commonly because no installed app can handle the URL scheme, or iOS hasn't whitelisted the scheme in LSApplicationQueriesSchemes — the catch block shows the toast \"无法打开链接\" (cannot open link). It indicates the OS refused or was unable to handle the link request.","triggerScenarios":"Calling openUrl() with a URL whose scheme no app registers (e.g. a custom scheme when the target app isn't installed); on iOS, a scheme not declared in LSApplicationQueriesSchemes so canOpenURL throws; malformed URLs; or openURL failing due to missing intent handlers on Android.","commonSituations":"Tapping an external link in markdown content when no browser or matching app is installed; iOS 9+ scheme-query restriction after adding new deeplinks; URL built with unencoded characters; testing on a fresh emulator with no browser app.","solutions":["Verify the URL scheme is one the device can handle (browser http/https links are safest) and that the URL is well-formed and properly encoded.","On iOS, add every custom scheme you query to LSApplicationQueriesSchemes in Info.plist.","On Android, ensure the URL has a valid https/http scheme or that an app exists that registers the custom scheme.","Handle the rejection yourself with a fallback: copy the URL to clipboard or open it inside an in-app WebView instead of relying on the OS.","Log the failing URL in the catch block to identify which link is broken."],"exampleFix":"// before\nexport default async function (url: string) {\n    try {\n        await Linking.canOpenURL(url);\n        return Linking.openURL(url);\n    } catch {\n        Toast.warn(\"无法打开链接\");\n    }\n}\n\n// after\nexport default async function (url: string) {\n    try {\n        const supported = await Linking.canOpenURL(url);\n        if (!supported) throw new Error(`unsupported: ${url}`);\n        return Linking.openURL(url);\n    } catch (e) {\n        console.warn('openUrl failed', url, e);\n        Toast.warn(\"无法打开链接\");\n        Clipboard.setString(url);\n    }\n}","handlingStrategy":"try-catch","validationCode":"import { Linking } from 'react-native';\n\nexport async function canOpen(url: string) {\n    try {\n        if (!/^https?:\\/\\//.test(url)) return false;\n        return await Linking.canOpenURL(url);\n    } catch {\n        return false;\n    }\n}\n\nif (await canOpen(url)) {\n    openUrl(url);\n} else {\n    Toast.warn('无法打开链接');\n}","typeGuard":"function isHttpUrl(url: string): boolean {\n    try {\n        const u = new URL(url);\n        return u.protocol === 'http:' || u.protocol === 'https:';\n    } catch {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    const supported = await Linking.canOpenURL(url);\n    if (!supported) throw new Error(`no handler for ${url}`);\n    await Linking.openURL(url);\n} catch (e) {\n    console.warn('openUrl failed', url, e);\n    Toast.warn('无法打开链接');\n    Clipboard.setString(url); // fallback so the user can still reach it\n}","preventionTips":["Prefer plain https:// links over custom schemes whenever possible.","On iOS, list every queried scheme in LSApplicationQueriesSchemes (Info.plist).","Sanitize/encode URLs built from user or remote content before opening.","Always check canOpenURL result rather than assuming it never throws, and provide a clipboard or WebView fallback."],"tags":["react-native","linking","deep-link","ios"],"backgroundTag":"cannot-open-url","analyzedSha":"d118b18b3d0c904400f7eea7bf99c0ceec6c1aee","analyzedAt":"2026-08-30T11:49:12.932Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}