juanfont/headscale · warning

executing command, stdout: %q stderr: %q, err: %w

Error message

executing command, stdout: %q stderr: %q, err: %w

What it means

Produced inside the retry closure of the integration helper assertCommandOutputContains when executing a command in a tailscale client container fails. It captures stdout, stderr, and the exec error so the eventual assertion failure shows full command output. Retried for up to 10 seconds with exponential backoff before assert.NoError fails the test.

Source

Thrown at integration/helpers.go:908

	}

	assert.NotEqualf(t, 0, report.PreferredDERP, "%q does not have a DERP relay", client.Hostname())
}

// assertCommandOutputContains executes a command with exponential backoff retry until the output
// contains the expected string or timeout is reached (10 seconds).
// This implements eventual consistency patterns and should be used instead of [time.Sleep]
// before executing commands that depend on network state propagation.
//
// Timeout: 10 seconds with exponential backoff
// Use cases: DNS resolution, route propagation, policy updates.
func assertCommandOutputContains(t *testing.T, c TailscaleClient, command []string, contains string) {
	t.Helper()

	_, err := backoff.Retry(t.Context(), func() (struct{}, error) {
		stdout, stderr, err := c.Execute(command)
		if err != nil {
			return struct{}{}, fmt.Errorf("executing command, stdout: %q stderr: %q, err: %w", stdout, stderr, err)
		}

		if !strings.Contains(stdout, contains) {
			return struct{}{}, fmt.Errorf("executing command, expected string %q not found in %q", contains, stdout) //nolint:err113
		}

		return struct{}{}, nil
	}, backoff.WithBackOff(backoff.NewExponentialBackOff()), backoff.WithMaxElapsedTime(10*time.Second))

	assert.NoError(t, err)
}

// dockertestMaxWait returns the maximum wait time for Docker-based test operations.
// Uses longer timeouts in CI environments to account for slower resource allocation
// and higher system load during automated testing.
func dockertestMaxWait() time.Duration {
	wait := 300 * time.Second //nolint

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Read the captured stdout/stderr in the assertion message to see the real exec failure
  2. Ensure prior setup steps (login, up) completed before asserting on command output
  3. Confirm the command exists in the client image for the tailscale version being tested
Defensive patterns

Strategy: retry

Validate before calling

// ensure the client's daemon is responsive before asserting
assertCommandOutputContains(t, c, []string{"tailscale", "status"}, "Logged out\|Running") // adapted to your flow

Try / catch

// the helper already retries for 10s with backoff and surfaces stdout/stderr;
// on failure, read the captured output instead of retrying manually

Prevention

When it happens

Trigger: Calling assertCommandOutputContains while c.Execute fails — e.g. running `tailscale status`/`ip route` before tailscaled is up, the container is restarting, or the binary/args are wrong.

Common situations: Tests asserting on DNS resolution or route propagation run before the client container's daemon is functional; SSH/exec to the container fails under load; command not present in the tailscale image version under test.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/25eb75a5989937e9. Report an issue: GitHub.