mihomo-party-org/clash-party · warning

Get service failed

Error message

Get service failed

What it means

Within getDefaultService, after finding the matching block for the device, the function scans its lines for one matching /^\(\d+\).*/ (the numbered service line). If the block exists but no numbered service line parses, it throws 'Get service failed' — an unexpected networksetup output format.

Source

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

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, ' ') })
  }
}

async function setDNS(dns: string, timeout?: number): Promise<void> {
  const service = await getDefaultService()
  try {
    await axios.post(
      'http://localhost/dns',
      { service, dns },

View on GitHub (pinned to 911e090537)

Solutions

  1. Inspect `networksetup -listnetworkserviceorder` output and compare its format with the expected '(1) ServiceName' pattern.
  2. Update the app if macOS changed the output format.
  3. Repair network services (remove/re-add the service in System Settings) to restore normal output.
  4. As a workaround set DNS manually via System Settings instead of this API.

Example fix

// expected block format
// (1) Wi-Fi
// (Hardware Port: Wi-Fi, Device: en0)
// if block lacks '(N) ' lines -> throws; re-add the service to restore format
Defensive patterns

Strategy: try-catch

Validate before calling

const { stdout: order } = await execPromise('networksetup -listnetworkserviceorder')
const block = order.split('\n\n').find((s) => s.includes(`Device: ${device}`))
const hasNumberedLine = !!block && block.split('\n').some((l) => /^\(\d+\).*/.test(l))
if (!hasNumberedLine) {
  // unexpected networksetup format — do not proceed
}

Try / catch

try {
  const service = await getDefaultService()
} catch (e) {
  if (e.message === 'Get service failed') {
    // networksetup output format changed or is corrupted; set DNS manually
  }
}

Prevention

When it happens

Trigger: service() → getDefaultService() where the `Device: <device>` block was found but none of its lines start with '(N)', e.g. localized/changed networksetup output format or malformed block.

Common situations: Non-English macOS locale or future macOS changing networksetup formatting; corrupted NetworkExtensions preferences producing a block without the numbered service header; output parsing assumptions broken by whitespace changes.

Related errors


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