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
- Read the captured stdout/stderr in the assertion message to see the real exec failure
- Ensure prior setup steps (login, up) completed before asserting on command output
- 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
- Sequence tests so login/up completes before output assertions
- Prefer the provided helpers over raw sleeps — they encode the backoff for you
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
- executing command, expected string %q not found in %q
- reading container logs: %w
- creating headscale container: %w
- creating tailscale node: %w
- starting headscale: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/25eb75a5989937e9.
Report an issue: GitHub.