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.

Solutions

  1. 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.
  2. On iOS, add every custom scheme you query to LSApplicationQueriesSchemes in Info.plist.
  3. On Android, ensure the URL has a valid https/http scheme or that an app exists that registers the custom scheme.
  4. 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.
  5. 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

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.

Appendix: 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)