{"record":{"id":"c20652b1117330b4","repo":"mihomo-party-org/clash-party","slug":"get-networkservice-failed","errorCode":null,"errorMessage":"Get networkservice failed","messagePattern":"Get networkservice failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/core/dns.ts","lineNumber":30,"sourceCode":"\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()\n  const { stdout: dns } = await execPromise(`networksetup -getdnsservers \"${service}\"`)\n  if (dns.startsWith(\"There aren't any DNS Servers set on\")) {\n    await patchAppConfig({ originDNS: 'Empty' })\n  } else {\n    await patchAppConfig({ originDNS: dns.trim().replace(/\\n/g, ' ') })\n  }\n}\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/core/dns.ts#L12-L48","documentation":"getDefaultService maps the default device (interface) to a macOS network service by scanning `networksetup -listnetworkserviceorder` output for a block containing `Device: <device>`. If no block matches the device, it throws 'Get networkservice failed'.","triggerScenarios":"service() → getDefaultService() with a device name (e.g. from a VPN utun interface) that does not appear under any `Device:` line in the networksetup order output.","commonSituations":"Default route is on a VPN utun* interface which networksetup does not list as a service; interface renamed or managed outside networksetup (e.g. custom daemon, USB tethering driver); macOS network services modified while the route points elsewhere.","solutions":["Check `networksetup -listnetworkserviceorder` contains a `Device: <your-device>` entry matching the default interface.","If the default device is a VPN utun, disable the VPN or set DNS manually while it's active.","Recreate/repair the network service in System Settings so it owns the physical device (en0/en1).","Retry after the network service for the active interface is properly configured."],"exampleFix":"// diagnostic\nroute -n get default   # e.g. interface: utun3\nnetworksetup -listnetworkserviceorder   # no 'Device: utun3' -> throws\n// fix: disconnect VPN so default route returns to en0 (which has a service)","handlingStrategy":"fallback","validationCode":"const { stdout: order } = await execPromise('networksetup -listnetworkserviceorder')\nif (!order.includes(`Device: ${device}`)) {\n  // device has no associated network service (e.g. VPN utun) — bail out early\n}","typeGuard":null,"tryCatchPattern":"try {\n  const service = await getDefaultService()\n} catch (e) {\n  if (e.message === 'Get networkservice failed') {\n    // default device is likely a VPN utun; fall back to manual DNS config\n  }\n}","preventionTips":["Disconnect VPNs before programmatic DNS changes on macOS.","Verify every physical interface has a matching network service in System Settings.","Log the networksetup order output when debugging."],"tags":["macos","networksetup","dns","vpn"],"backgroundTag":"network-service-not-found","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}