{"record":{"id":"0fefd9ae13949130","repo":"mihomo-party-org/clash-party","slug":"get-device-failed","errorCode":null,"errorMessage":"Get device failed","messagePattern":"Get device failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/core/dns.ts","lineNumber":22,"sourceCode":"import axios from 'axios'\nimport { getAppConfig, patchAppConfig } from '../config'\n\nconst execPromise = promisify(exec)\nconst helperSocketPath = '/tmp/mihomo-party-helper.sock'\n\nlet setPublicDNSTimer: NodeJS.Timeout | null = null\nlet recoverDNSTimer: NodeJS.Timeout | null = null\n\ninterface DNSOperationOptions {\n  force?: boolean\n  timeout?: number\n}\n\nexport async function getDefaultDevice(): Promise<string> {\n  const { stdout: deviceOut } = await execPromise(`route -n get default`)\n  let device = deviceOut.split('\\n').find((s) => s.includes('interface:'))\n  device = device?.trim().split(' ').slice(1).join(' ')\n  if (!device) throw new Error('Get device failed')\n  return device\n}\n\nasync function getDefaultService(): Promise<string> {\n  const device = await getDefaultDevice()\n  const { stdout: order } = await execPromise(`networksetup -listnetworkserviceorder`)\n  const block = order.split('\\n\\n').find((s) => s.includes(`Device: ${device}`))\n  if (!block) throw new Error('Get networkservice failed')\n  for (const line of block.split('\\n')) {\n    if (line.match(/^\\(\\d+\\).*/)) {\n      return line.trim().split(' ').slice(1).join(' ')\n    }\n  }\n  throw new Error('Get service failed')\n}\n\nasync function getOriginDNS(): Promise<void> {\n  const service = await getDefaultService()","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/core/dns.ts#L4-L40","documentation":"getDefaultDevice runs `route -n get default` (macOS) to find the default network interface, extracts the line containing 'interface:', and throws 'Get device failed' if no interface can be determined — either the route command output lacked such a line or parsing yielded an empty string.","triggerScenarios":"Calling device() or getDefaultService()/service() (which call getDefaultDevice) on macOS when `route -n get default` produces no 'interface:' line — e.g. no default route exists (offline, only loopback up, VPN removing default route).","commonSituations":"Machine fully offline or Wi-Fi/Ethernet disconnected; VPN (including this app's TUN mode) removed the default route; `route` command not behaving as expected on unusual macOS setups; running on non-macOS where the command fails.","solutions":["Check network connectivity and that a default route exists: `route -n get default` should include 'interface:'.","Reconnect Wi-Fi/Ethernet or bring up an interface with a default gateway.","If a VPN/TUN removed the default route, re-add it or run the DNS operation while a normal route is present.","Ensure the app runs on macOS where `route -n get default` is supported."],"exampleFix":"// before\nconst device = await getDefaultDevice() // throws when offline\n// after\ntry {\n  const device = await getDefaultDevice()\n} catch {\n  // prompt user to connect to a network\n}","handlingStrategy":"try-catch","validationCode":"import { exec } from 'child_process'\nconst { stdout } = await new Promise<...>(exec('route -n get default'))\nconst hasDefaultRoute = /interface:\\s*\\S+/.test(stdout)\nif (!hasDefaultRoute) {\n  // network is down or no default gateway; don't call getDefaultDevice\n}","typeGuard":null,"tryCatchPattern":"try {\n  const device = await getDefaultDevice()\n} catch (e) {\n  if (e.message === 'Get device failed') {\n    // check connectivity / default route, then retry\n  }\n}","preventionTips":["Check `route -n get default` succeeds before DNS manipulation.","Handle VPN/TUN setups that remove the default route.","Only run these macOS-only commands on macOS."],"tags":["network","macos","dns","routing"],"backgroundTag":"no-default-route","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}