{"record":{"id":"c7d5f31d7e87e868","repo":"mihomo-party-org/clash-party","slug":"i18next-t-profiles-error-urlparammissing","errorCode":null,"errorMessage":"i18next.t('profiles.error.urlParamMissing')","messagePattern":"i18next\\.t\\('profiles\\.error\\.urlParamMissing'\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/deeplink.ts","lineNumber":25,"sourceCode":"\nexport function findDeepLink(args: string[]): string | undefined {\n  return args.find((arg) => {\n    const lower = arg.toLowerCase()\n    return lower.startsWith('clash://') || lower.startsWith('mihomo://')\n  })\n}\n\nexport async function handleDeepLink(url: string): Promise<void> {\n  if (!findDeepLink([url])) return\n\n  const urlObj = new URL(url)\n  switch (urlObj.host) {\n    case 'install-config': {\n      try {\n        const profileUrl = urlObj.searchParams.get('url')\n        const profileName = urlObj.searchParams.get('name')\n        if (!profileUrl) {\n          throw new Error(i18next.t('profiles.error.urlParamMissing'))\n        }\n        await addProfileItem({\n          type: 'remote',\n          name: profileName ?? undefined,\n          url: profileUrl\n        })\n        mainWindow?.webContents.send('profileConfigUpdated')\n        new Notification({ title: i18next.t('profiles.notification.importSuccess') }).show()\n      } catch (e) {\n        safeShowErrorBox('profiles.error.importFailed', `${url}\\n${e}`)\n      }\n      break\n    }\n    case 'install-plugin': {\n      let plugin: IPluginItem\n      try {\n        const pluginUrl = urlObj.searchParams.get('url')\n        if (!pluginUrl) {","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/deeplink.ts#L7-L43","documentation":"This is an application-level error thrown by handleDeepLink in src/main/deeplink.ts:25 when a deeplink URL targeting the 'install-config' host is missing its required 'url' query parameter. The code reads urlObj.searchParams.get('url') and throws before attempting to add the profile, because addProfileItem with type 'remote' cannot proceed without a profile URL. The message is an i18next key ('profiles.error.urlParamMissing') resolved to a localized user-facing string.","triggerScenarios":"Handling a deeplink like clash://install-config?name=foo without ?url=..., or with url= (empty value, since searchParams.get returns '' which is falsy and fails the !profileUrl check).","commonSituations":"Users copy/paste truncated subscription links from web pages; marketing sites generate deeplinks with missing or empty url params; URL encoding strips the parameter; bots or scripts invoke the deeplink scheme programmatically without the full query string.","solutions":["Add a valid url query parameter to the deeplink, e.g. clash://install-config?url=https%3A%2F%2Fexample.com%2Fprofile.yaml","Ensure the url parameter is URL-encoded (encodeURIComponent) when constructing the deeplink so it is not dropped or split","If the link comes from a QR code or shared text, verify it was not truncated before the query string","In handleDeepLink, catch this error and show a localized error box instead of crashing (the sibling install-plugin branch already does safeShowErrorBox)"],"exampleFix":"// before\nconst link = 'clash://install-config?name=myprofile'\n// after\nconst url = encodeURIComponent('https://example.com/profile.yaml')\nconst link = `clash://install-config?url=${url}&name=myprofile`","handlingStrategy":"validation","validationCode":"const url = new URL(rawLink)\nconst profileUrl = url.searchParams.get('url')\nif (!profileUrl) {\n  throw new Error(i18next.t('profiles.error.urlParamMissing'))\n}","typeGuard":"function hasInstallConfigUrl(link: string): link is string & { __brand: 'validInstallConfig' } {\n  try {\n    return !!new URL(link).searchParams.get('url')\n  } catch {\n    return false\n  }\n}","tryCatchPattern":"try {\n  await handleDeepLink(link)\n} catch (e) {\n  if (String(e).includes('urlParamMissing') || e instanceof Error) {\n    safeShowErrorBox('profiles.error.urlParamMissing', `${e}`)\n  }\n}","preventionTips":["Always URL-encode the url query parameter when generating deeplinks (encodeURIComponent)","Test generated deeplinks in a browser/shell before distributing them","Copy the full link including the entire query string; watch for truncation in QR codes and chat apps","Validate deeplink parameters at the entry point of handleDeepLink and fail fast with a localized message"],"tags":["deeplink","url-parsing","validation","i18n"],"backgroundTag":"missing-required-url-parameter","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}