mihomo-party-org/clash-party · error

Get networkservice failed

Error message

Get networkservice failed

What it means

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'.

Source

Thrown at src/main/core/dns.ts:30

interface DNSOperationOptions {
  force?: boolean
  timeout?: number
}

export async function getDefaultDevice(): Promise<string> {
  const { stdout: deviceOut } = await execPromise(`route -n get default`)
  let device = deviceOut.split('\n').find((s) => s.includes('interface:'))
  device = device?.trim().split(' ').slice(1).join(' ')
  if (!device) throw new Error('Get device failed')
  return device
}

async function getDefaultService(): Promise<string> {
  const device = await getDefaultDevice()
  const { stdout: order } = await execPromise(`networksetup -listnetworkserviceorder`)
  const block = order.split('\n\n').find((s) => s.includes(`Device: ${device}`))
  if (!block) throw new Error('Get networkservice failed')
  for (const line of block.split('\n')) {
    if (line.match(/^\(\d+\).*/)) {
      return line.trim().split(' ').slice(1).join(' ')
    }
  }
  throw new Error('Get service failed')
}

async function getOriginDNS(): Promise<void> {
  const service = await getDefaultService()
  const { stdout: dns } = await execPromise(`networksetup -getdnsservers "${service}"`)
  if (dns.startsWith("There aren't any DNS Servers set on")) {
    await patchAppConfig({ originDNS: 'Empty' })
  } else {
    await patchAppConfig({ originDNS: dns.trim().replace(/\n/g, ' ') })
  }
}

View on GitHub (pinned to 911e090537)

Solutions

  1. Check `networksetup -listnetworkserviceorder` contains a `Device: <your-device>` entry matching the default interface.
  2. If the default device is a VPN utun, disable the VPN or set DNS manually while it's active.
  3. Recreate/repair the network service in System Settings so it owns the physical device (en0/en1).
  4. Retry after the network service for the active interface is properly configured.

Example fix

// diagnostic
route -n get default   # e.g. interface: utun3
networksetup -listnetworkserviceorder   # no 'Device: utun3' -> throws
// fix: disconnect VPN so default route returns to en0 (which has a service)
Defensive patterns

Strategy: fallback

Validate before calling

const { stdout: order } = await execPromise('networksetup -listnetworkserviceorder')
if (!order.includes(`Device: ${device}`)) {
  // device has no associated network service (e.g. VPN utun) — bail out early
}

Try / catch

try {
  const service = await getDefaultService()
} catch (e) {
  if (e.message === 'Get networkservice failed') {
    // default device is likely a VPN utun; fall back to manual DNS config
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/c20652b1117330b4. Report an issue: GitHub.