{"record":{"id":"02ac031654d1927c","repo":"mihomo-party-org/clash-party","slug":"direct-remote-profile-fetch-failed-id-id-url","errorCode":null,"errorMessage":"Direct remote profile fetch failed id=${id} url=${redactSubscriptionUrl(profileUrl)}; trying proxy fallback","messagePattern":"Direct remote profile fetch failed id=(.+?) url=(.+?); trying proxy fallback","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/main/config/profile.ts","lineNumber":498,"sourceCode":"      url: profileUrl,\n      mixedPort,\n      userAgent: item.userAgent || userAgent || `mihomo.party/v${app.getVersion()} (clash.meta)`,\n      ageSecretKey: newItem.ageSecretKey,\n      authToken: item.authToken,\n      substore: newItem.substore || false\n    }\n\n    const fetchSub = (useProxy: boolean, timeout: number): Promise<FetchResult> =>\n      fetchAndValidateSubscription({ ...baseOptions, useProxy, timeout })\n\n    let result: FetchResult\n    if (newItem.useProxy || newItem.substore) {\n      result = await fetchSub(Boolean(newItem.useProxy), userItemTimeoutMs)\n    } else {\n      try {\n        result = await fetchSub(false, userItemTimeoutMs)\n      } catch (directError) {\n        await profileLogger.warn(\n          `Direct remote profile fetch failed id=${id} url=${redactSubscriptionUrl(\n            profileUrl\n          )}; trying proxy fallback`,\n          directError\n        )\n        try {\n          // smart fallback\n          result = await fetchSub(true, subscriptionTimeout)\n        } catch {\n          throw directError\n        }\n      }\n    }\n\n    const { data, headers } = result\n\n    if (headers['content-disposition'] && newItem.name === 'Remote File') {\n      newItem.name = parseFilename(headers['content-disposition'])","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/config/profile.ts#L480-L516","documentation":"When creating a profile from a remote subscription URL, the app first tries a direct fetch. If it fails, it logs this warning (with the profile id and redacted URL) before automatically retrying through a proxy/substore fallback. Note the message is a logger.warn argument, not a thrown Error — users see it in logs; a thrown error only occurs if the proxy fallback also fails.","triggerScenarios":"The subscription host is unreachable directly: DNS failure, TLS interception, GFW/regional blocking, server blocks non-proxied requests, wrong URL, or the machine has no direct internet access but a proxy is configured.","commonSituations":"Users in censored networks fetching blocked subscription URLs; subscription servers that geo-block or rate-limit; expired subscription links returning errors; corporate networks requiring a proxy for all outbound HTTP.","solutions":["Nothing to fix if the proxy fallback succeeds — this warning is informational; check subsequent log lines for the fallback result.","Enable 'use proxy' or substore option for the profile so the first fetch goes through the proxy.","Verify the subscription URL is correct and still valid (test in a browser).","Ensure the app's proxy settings point at a working local proxy core, then retry creating the profile."],"exampleFix":"// before (log noise from repeated direct failures)\nconst result = await fetchSub(false, timeoutMs)\n// after\nconst result = await fetchSub(Boolean(newItem.useProxy), timeoutMs) // with useProxy enabled in profile settings","handlingStrategy":"fallback","validationCode":"// Pre-validate the subscription URL before creating the profile:\ntry {\n  new URL(profileUrl)\n} catch {\n  throw new Error('Invalid subscription URL')\n}\nconst reachable = await fetch(profileUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }).then(r => r.ok).catch(() => false)\nif (!reachable) console.warn('Subscription unreachable directly — proxy fallback will be used')","typeGuard":null,"tryCatchPattern":"try {\n  result = await fetchSub(false, timeoutMs)\n} catch (directError) {\n  logger.warn('Direct fetch failed; using proxy fallback', directError)\n  result = await fetchSub(true, timeoutMs) // fall back to proxy path\n}","preventionTips":["Enable the proxy/substore option for profiles hosted behind blocked or geo-restricted URLs.","Keep a working local proxy running so the fallback path succeeds.","Verify subscription URLs periodically (they expire / rate-limit).","Treat this log line as informational; only act if the subsequent proxy fetch also fails."],"tags":["network","proxy","logging"],"backgroundTag":"direct-fetch-failed-proxy-fallback","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}