tailscale/tailscale · error

res.Error

Error message

res.Error

What it means

diskutilInfo runs `diskutil info -plist <id>` for each candidate disk that diskutil list reported and is not a boot disk; this error wraps a failed exec. Typical cause: the disk disappeared between list and info (USB/SD unplugged), or diskutil refused the identifier (invalid/ambiguous id, permissions).

Source

Thrown at client/local/local.go:754

// subject to change between releases.
func (lc *Client) SetComponentDebugLogging(ctx context.Context, component string, d time.Duration) error {
	if !buildfeatures.HasDebug {
		return feature.ErrUnavailable
	}
	body, err := lc.send(ctx, "POST",
		fmt.Sprintf("/localapi/v0/component-debug-logging?component=%s&secs=%d",
			url.QueryEscape(component), int64(d.Seconds())), 200, nil)
	if err != nil {
		return fmt.Errorf("error %w: %s", err, body)
	}
	var res struct {
		Error string
	}
	if err := json.Unmarshal(body, &res); err != nil {
		return err
	}
	if res.Error != "" {
		return errors.New(res.Error)
	}
	return nil
}

// Status returns the Tailscale daemon's status.
func Status(ctx context.Context) (*ipnstate.Status, error) {
	return defaultClient.Status(ctx)
}

// Status returns the Tailscale daemon's status.
//
// API maturity: this is considered a stable API.
func (lc *Client) Status(ctx context.Context) (*ipnstate.Status, error) {
	return lc.status(ctx, "")
}

// StatusWithoutPeers returns the Tailscale daemon's status, without the peer info.
func StatusWithoutPeers(ctx context.Context) (*ipnstate.Status, error) {

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Re-run the command with the device connected and stable; auto-detection re-lists disks each run.
  2. If the device keeps dropping, try another port/cable/reader, then verify with `diskutil list` run twice and comparing output.
  3. Pass an explicit stable target with `--disk /dev/diskN` once you've confirmed the id via `diskutil list`.
  4. If it persists, run `diskutil info -plist diskN` manually to see diskutil's stderr and rule out system-level disk errors (check Disk Utility / system log).

Example fix

// before: card removed mid-scan
$ tailscale configure flash-appliance
Error: diskutil info disk4: exit status 1   # disk4 vanished

// after: reconnect, then re-run or be explicit
$ diskutil list | grep external   # confirm disk4 present
$ tailscale configure flash-appliance --disk /dev/disk4
Defensive patterns

Strategy: retry

Validate before calling

// optional pre-check that the device still exists
if _, err := exec.Command("diskutil", "info", id).Output(); err != nil {
    return fmt.Errorf("disk %s already gone; re-run discovery", id)
}

Try / catch

// Go: retry transient disk-disappearance around diskutil info
var d diskCandidate
for attempt := 0; attempt < 3; attempt++ {
    var err error
    d, err = diskutilInfo(ctx, id)
    if err == nil {
        break
    }
    var ee *exec.ExitError
    if !errors.As(err, &ee) {
        return err // not a transient exec failure
    }
    time.Sleep(500 * time.Millisecond) // let USB re-enumerate
}

Prevention

When it happens

Trigger: During `tailscale configure flash-appliance` auto-detection: a removable drive listed by `diskutil list` is yanked out before `diskutil info` runs, causing ExitError; also seen when diskutil is missing from PATH or when the id handed to diskutil is stale.

Common situations: User unplugs the target USB/SD card mid-command; a flaky card reader dropping the device; disks changing while macOS re-enumerates (thunderbolt/USB hub renegotiation); running in environments where diskutil is restricted.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/7ae5adaff8375b24. Report an issue: GitHub.