netbirdio/netbird · error

execute command: %w

Error message

execute command: %w

What it means

Returned by executeSSHCommand when the remote command fails for a reason other than the cases already handled: a non-zero remote exit is converted to os.Exit(ExitError.ExitStatus()), a missing exit status (ExitMissingError) is logged and treated as success, and context cancellation/deadline returns nil. Whatever remains — session setup failures, I/O errors on the channel, permission denied opening a session — is wrapped as `execute command: %w`.

Source

Thrown at client/cmd/ssh.go:590

	}

	if err != nil {
		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
			return nil
		}

		var exitErr *ssh.ExitError
		if errors.As(err, &exitErr) {
			os.Exit(exitErr.ExitStatus())
		}

		var exitMissingErr *ssh.ExitMissingError
		if errors.As(err, &exitMissingErr) {
			log.Debugf("Remote command exited without exit status: %v", err)
			return nil
		}

		return fmt.Errorf("execute command: %w", err)
	}
	return nil
}

// openSSHTerminal opens an interactive SSH terminal.
func openSSHTerminal(ctx context.Context, c *sshclient.Client) error {
	if err := c.OpenTerminal(ctx); err != nil {
		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
			return nil
		}

		var exitMissingErr *ssh.ExitMissingError
		if errors.As(err, &exitMissingErr) {
			log.Debugf("Remote terminal exited without exit status: %v", err)
			return nil
		}

		return fmt.Errorf("open terminal: %w", err)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Re-run the command; if it consistently fails while interactive `netbird ssh <host>` works, compare with and without --pty.
  2. Check peer health with `netbird status -d` and the remote sshd logs for rejected session/channel requests.
  3. Capture stderr of the CLI to see the wrapped cause after `execute command:` — it distinguishes channel I/O errors from protocol errors.
  4. If the command must surface the remote exit code, verify you are on a version where ExitError maps to os.Exit (non-zero exits propagate, this error is for the other failure modes).
  5. For scripted use, add a timeout with --timeout or wrap in timeout(1) so hangs surface as context errors (handled as nil/success) instead of channel errors.

Example fix

# before
netbird ssh peer1 -- make build
# -> execute command: session request failed

# after
netbird status -d                       # confirm peer healthy
netbird ssh peer1 -- make build         # retry once peer is responsive
# or drop PTY for non-interactive commands: avoid --pty here
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight the command path before the interactive parts of a script
if command == "" {
	return errors.New("no command given; pass it after the host")
}
if port < 1 || port > 65535 {
	return fmt.Errorf("bad --port %d", port)
}
// confirm peer is reachable so exec failures are not connectivity noise
if !peerConnected(host) { return fmt.Errorf("peer %s not connected", host) }

Try / catch

if err := executeSSHCommand(sshCtx, c, command); err != nil {
	var exitErr *ssh.ExitError
	switch {
	case errors.As(err, &exitErr):
		os.Exit(exitErr.ExitStatus()) // propagate remote exit code
	case isExitMissing(err):
		return nil // remote died without status: treat as done
	case errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
		return nil
	default:
		return fmt.Errorf("execute command: %w", err) // session/IO failure
	}
}

Prevention

When it happens

Trigger: `netbird ssh <host> <command...>` (optionally --pty) where the SSH session cannot be opened or the command stream fails mid-run: session channel rejected by the peer, stdin/stdout piping errors, terminal request refused when --pty is set, or the connection dropping during execution without a clean exit status.

Common situations: Running commands through a heavily loaded or half-dead peer; requesting a PTY for a non-interactive command on peers that restrict channel requests; piping large output that breaks the channel; commands killed by the remote side without an exit-status message.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/9fb0d00e13c90603. Report an issue: GitHub.