mihomo-party-org/clash-party · error

Get device failed

Error message

Get device failed

What it means

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.

Source

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

import axios from 'axios'
import { getAppConfig, patchAppConfig } from '../config'

const execPromise = promisify(exec)
const helperSocketPath = '/tmp/mihomo-party-helper.sock'

let setPublicDNSTimer: NodeJS.Timeout | null = null
let recoverDNSTimer: NodeJS.Timeout | null = null

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()

View on GitHub (pinned to 911e090537)

Solutions

  1. Check network connectivity and that a default route exists: `route -n get default` should include 'interface:'.
  2. Reconnect Wi-Fi/Ethernet or bring up an interface with a default gateway.
  3. If a VPN/TUN removed the default route, re-add it or run the DNS operation while a normal route is present.
  4. Ensure the app runs on macOS where `route -n get default` is supported.

Example fix

// before
const device = await getDefaultDevice() // throws when offline
// after
try {
  const device = await getDefaultDevice()
} catch {
  // prompt user to connect to a network
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { exec } from 'child_process'
const { stdout } = await new Promise<...>(exec('route -n get default'))
const hasDefaultRoute = /interface:\s*\S+/.test(stdout)
if (!hasDefaultRoute) {
  // network is down or no default gateway; don't call getDefaultDevice
}

Try / catch

try {
  const device = await getDefaultDevice()
} catch (e) {
  if (e.message === 'Get device failed') {
    // check connectivity / default route, then retry
  }
}

Prevention

When it happens

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

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

Related errors


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