maotoumao/MusicFree · warning
无法打开链接
Error message
无法打开链接
What it means
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.
Source
Thrown at src/utils/openUrl.ts:9
import { Linking } from "react-native";
import Toast from "./toast";
export default async function (url: string) {
try {
await Linking.canOpenURL(url);
return Linking.openURL(url);
} catch {
Toast.warn("无法打开链接");
}
}
View on GitHub (pinned to d118b18b3d)
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.
Example fix
// before
export default async function (url: string) {
try {
await Linking.canOpenURL(url);
return Linking.openURL(url);
} catch {
Toast.warn("无法打开链接");
}
}
// after
export default async function (url: string) {
try {
const supported = await Linking.canOpenURL(url);
if (!supported) throw new Error(`unsupported: ${url}`);
return Linking.openURL(url);
} catch (e) {
console.warn('openUrl failed', url, e);
Toast.warn("无法打开链接");
Clipboard.setString(url);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
import { Linking } from 'react-native';
export async function canOpen(url: string) {
try {
if (!/^https?:\/\//.test(url)) return false;
return await Linking.canOpenURL(url);
} catch {
return false;
}
}
if (await canOpen(url)) {
openUrl(url);
} else {
Toast.warn('无法打开链接');
} Type guard
function isHttpUrl(url: string): boolean {
try {
const u = new URL(url);
return u.protocol === 'http:' || u.protocol === 'https:';
} catch {
return false;
}
} Try / catch
try {
const supported = await Linking.canOpenURL(url);
if (!supported) throw new Error(`no handler for ${url}`);
await Linking.openURL(url);
} catch (e) {
console.warn('openUrl failed', url, e);
Toast.warn('无法打开链接');
Clipboard.setString(url); // fallback so the user can still reach it
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30).
Data as JSON: /api/errors/ca57f397c092224a.
Report an issue: GitHub.