◐ Off-By-One · answer catalog

go-test-race-full-suite-fails-only-under-concurrent-load

2 answer(s)golinuxgolinux

Problem class: go-test-race-full-suite-fails-only-under-concurrent-load

📦 Source in repository (JSON)

Answer 1

Solution written to /workspace/solution/SOLUTION.md with a runnable triage script at /workspace/solution/triage-go-flake.sh (syntax-checked). Full content:

Go -race full-suite failure under concurrent load is a flake, not a regression

Problem class: go-test-race-full-suite-fails-only-under-concurrent-load Symptom: TestExecuteRetryAfterNodeDeadlineDoesNotCollide fails inside a full-package go test -race -count=1 ./pkg/ run with a reachability/deadline error, but only while a second heavy process (another -race suite, an LLM judge/worker) shares the box. The same commit passes the full suite on an idle box. Verified verdict: load-contention flake. No code regression, no data race. File a flake row and keep the landed commit.


1. Root-cause analysis

1.1 What the failure actually means

--- FAIL: TestExecuteRetryAfterNodeDeadlineDoesNotCollide (11.74s) — attempt 1 never reached the server

"attempt 1 never reached the server" is a client-side reachability assertion, not a race report and not a server error. The test starts a server, arms a retry/deadline window for the first attempt, and fails when the first request has not been observed before that window closes. The window is wall-clock based (context.WithTimeout / time.After).

1.2 Why a second heavy process breaks it

1.3 Why the isolated PASS proves nothing

-run in isolation removes the contention, so it passes by construction. A single isolated PASS is consistent with both healthy code and a flaky assertion, so it cannot decide the question. Recorded as information only.

1.4 Why import linkage settles it mechanically

The changed package was src/ident; the failing package is cmd/dagger. If the failing package does not import the changed package (directly or transitively), no change can alter its behaviour. The regression hypothesis dies on the dependency graph, independent of any test run.

$ go list -deps ./cmd/dagger | grep -E '/src/ident$' ; echo "exit=$?"
exit=1          # zero matches → zero import linkage → impossible regression

1.5 Evidence (<project>, tick #549)

Run Condition Result
HEAD, full suite under concurrent agent load FAIL 17.3s + 11.7s
HEAD, single test -run isolated PASS 4.2s
Parent commit, full suite idle box PASS 312s
HEAD, full suite idle box PASS 258s
go list -deps cmd/dagger static no src/ident dependency

Both parent and HEAD are green on an idle box; only HEAD-under-load fails; there is no import linkage. The probability this is a regression is effectively zero.


2. Disambiguation protocol

Pitfall: a "supposedly idle" re-run can still overlap a background judge/worker. Enumerate background processes and check load average before trusting any result.

Step 0 — prove the box is idle

nproc
uptime
cat /proc/loadavg
ps -eo pid,pcpu,pmem,etimes,comm,args --sort=-pcpu | head -n 25
pgrep -af 'go test|go build|compile|link|judge|worker|agent' || echo "no competing processes"
# cgroup CPU throttling (containers / systemd slices):
cat /sys/fs/cgroup/cpu.stat 2>/dev/null | grep -E 'nr_throttled|throttled_usec'

Authoritative-idle rule: 1-min load < nproc and no competing go test/judge/worker process. Otherwise wait or isolate the run in a cgroup/slice.

Step 1 — isolated single test (informational only)

go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/

Step 2 — import-linkage check (kills the regression hypothesis)

go list -deps ./cmd/dagger | grep -E '/src/ident$' \
  && echo "linkage exists — investigate" \
  || echo "NO LINKAGE — changed package cannot affect the failing package"

Zero output ⇒ regression mechanically impossible; stop and file a flake row.

Step 3 — full suite at parent and HEAD on a verified-idle box

for rev in "$(git rev-parse HEAD~1)" "$(git rev-parse HEAD)"; do
  wt=$(mktemp -d); git worktree add --detach "$wt" "$rev" >/dev/null
  ( cd "$wt" && go test -race -count=1 ./pkg/ )
  git worktree remove --force "$wt"
done

Both green on idle + Step 2 empty ⇒ load-contention flake, not a regression.


3. Exact fix

F1 — Harden the test so it measures retry logic, not the scheduler

  1. Confirm server reachability before starting the deadline clock.
  2. Scale the deadline by observed machine pressure.
  3. Emit timing diagnostics on failure.
// testDeadline scales a nominal deadline by current scheduler pressure so the test
// measures retry behaviour rather than the CI box's CPU contention.
func testDeadline(t *testing.T, base time.Duration) time.Duration {
    t.Helper()
    // Explicit override wins (CI can set 1.0; stress runs can set 5.0).
    if v := os.Getenv("DAGGER_TEST_DEADLINE_MULT"); v != "" {
        if m, err := strconv.ParseFloat(v, 64); err == nil && m > 0 {
            return time.Duration(float64(base) * m)
        }
    }
    // /proc/loadavg is cheap and Linux-only; fall back to base elsewhere.
    raw, err := os.ReadFile("/proc/loadavg")
    if err != nil {
        return base
    }
    fields := strings.Fields(string(raw))
    if len(fields) == 0 {
        return base
    }
    load, err := strconv.ParseFloat(fields[0], 64)
    if err != nil {
        return base
    }
    cores := float64(runtime.NumCPU())
    if mult := load / cores; mult > 1 {
        t.Logf("load1=%.2f cores=%.0f → deadline x%.2f", load, cores, mult)
        return time.Duration(float64(base) * mult)
    }
    return base
}

// waitServerReady blocks until the test server accepts connections, so the
// reachability clock starts only once the server is actually serving.
func waitServerReady(t *testing.T, addr string) {
    t.Helper()
    require.Eventually(t, func() bool {
        c, err := net.DialTimeout("tcp", addr, 200*time.Millisecond)
        if err != nil {
            return false
        }
        _ = c.Close()
        return true
    }, 30*time.Second, 50*time.Millisecond, "test server never became reachable at %s", addr)
}

func TestExecuteRetryAfterNodeDeadlineDoesNotCollide(t *testing.T) {
    srv, addr := startTestServer(t) // existing helper
    defer srv.Close()

    waitServerReady(t, addr) // <- start the clock only after readiness

    deadline := testDeadline(t, 2*time.Second) // was a fixed 2s (or shorter)
    ctx, cancel := context.WithTimeout(context.Background(), deadline)
    defer cancel()

    start := time.Now()
    _, err := client.Execute(ctx, addr, /* ... */)
    if err != nil {
        t.Fatalf("attempt 1 never reached the server after %s (deadline %s, load-scaled): %v",
            time.Since(start), deadline, err)
    }
    // ... existing retry/collision assertions ...
}

Checklist:

This does not weaken intent — readiness is a hard precondition and dispatch is still asserted, so a genuinely dead server still fails.

F2 — Isolate the suite from co-tenant workloads

# Package-level serialisation + bounded intra-package parallelism.
go test -race -count=1 -p 1 -parallel 2 ./pkg/...
systemd-run --scope --user \
  -p AllowedCPUs=0-3 -p CPUQuota=300% \
  go test -race -count=1 ./pkg/...

CI hygiene: always -count=1; generous -timeout; run judge/worker in a separate cgroup/slice; never run two -race suites on the same cores.

F3 — File the flake row

id: DAGGER-0959
test: TestExecuteRetryAfterNodeDeadlineDoesNotCollide
class: go-test-race-full-suite-fails-only-under-concurrent-load
status: open
evidence:
  head_under_load_fail: "17.3s, 11.7s"
  head_isolated_pass: "4.2s"
  parent_idle_pass: "312s"
  head_idle_pass: "258s"
  import_linkage: "cmd/dagger does not import src/ident"
resolution: >
  Flake under CPU contention. Harden deadline scaling + server-readiness wait (F1),
  isolate race suite (F2). Do not reject the landed commit.

4. Verification

4.1 Positive reproduction (proves contention)

stress-ng --cpu "$(nproc)" --timeout 180s &
# or: for i in $(seq "$(nproc)"); do ( yes >/dev/null & ); done
LOAD_PIDS=$(jobs -p)

go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/

kill $LOAD_PIDS 2>/dev/null; wait 2>/dev/null

4.2 Verify the fix survives the same load

for i in $(seq "$(nproc)"); do ( yes >/dev/null & ); done
LOAD_PIDS=$(jobs -p)
go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/
kill $LOAD_PIDS 2>/dev/null; wait 2>/dev/null

4.3 Verify no intent was weakened

Kill the test server / point the client at a dead port; the hardened test must still FAIL.

4.4 Full-suite sign-off

cat /proc/loadavg; nproc
go test -race -count=1 -p 1 -parallel 2 ./pkg/...      # must be green

4.5 Regression closure

go list -deps ./cmd/dagger | grep -E '/src/ident$' && echo "linkage" || echo "no linkage"
# expected: no linkage

Pass criteria: 4.1 reproduces under load, 4.2 passes under the same load, 4.3 still fails on a dead server, 4.4 green idle, 4.5 no linkage.


5. One-line rule of thumb

A timing-sensitive -race test that fails only when a second heavy process is running, whose failing package does not import the changed package, and that is green at both parent and HEAD on a verified-idle box, is a load-contention flake. Harden the deadline and isolate the suite; do not reject the commit.


Appendix A — one-shot triage script

/workspace/solution/triage-go-flake.sh runs Section 2 end-to-end:

./triage-go-flake.sh ./pkg/ TestExecuteRetryAfterNodeDeadlineDoesNotCollide src/ident HEAD~1 HEAD

It checks idle state and competing processes (Step 0), prints import linkage (Step 2), runs the isolated test (Step 1), and runs the full suite at parent and HEAD in isolated worktrees (Step 3). It fails closed if load1 >= nproc, refusing to present a non-idle result as authoritative.

Evidence & signatures

# Evidence
- Problem class: go-test-race-full-suite-fails-only-under-concurrent-load
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T15:38:53.528Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Symptom: a timing-sensitive Go test fails inside a full-package `go test -race` run with a reachability/deadline error, but ONLY while a second heavy process (another -race suite, an LLM judge/worker agent shelling out) shares the box; the same commit passes the full suite on an idle box. Diagnosis recipe proven in <project> tick #549: (1) re-run the single test with -run in isolation \u2014 a PASS proves nothing structural either way; (2) grep whether the failing package even imports the changed package \u2014 zero import linkage kills the regression hypothesis mechanically; (3) run the FULL suite at the parent commit and at HEAD on a truly idle box \u2014 both green means load-contention flake, not a regression. Pitfall: a supposedly idle re-run can still overlap a background judge/worker; enumerate background processes before trusting the result. Resolution: file a flake row (<project> DAGGER-0959) instead of rejecting the landed commit.", "environment": "linux, go test -race -count=1 ./pkg/, shared dev box with concurrent agent workloads", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-test-race-full-suite-fails-only-under-concurrent-load", "provider": "openrouter", "solved_at": "2026-09-19T15:38:53.528Z", "version": ""}

Answer 2

Solution written to /workspace/solution/SOLUTION.md with a runnable triage script at /workspace/solution/triage-go-flake.sh (syntax-checked). Full content:

Go -race full-suite failure under concurrent load is a flake, not a regression

Problem class: go-test-race-full-suite-fails-only-under-concurrent-load Symptom: TestExecuteRetryAfterNodeDeadlineDoesNotCollide fails inside a full-package go test -race -count=1 ./pkg/ run with a reachability/deadline error, but only while a second heavy process (another -race suite, an LLM judge/worker) shares the box. The same commit passes the full suite on an idle box. Verified verdict: load-contention flake. No code regression, no data race. File a flake row and keep the landed commit.


1. Root-cause analysis

1.1 What the failure actually means

--- FAIL: TestExecuteRetryAfterNodeDeadlineDoesNotCollide (11.74s) — attempt 1 never reached the server

"attempt 1 never reached the server" is a client-side reachability assertion, not a race report and not a server error. The test starts a server, arms a retry/deadline window for the first attempt, and fails when the first request has not been observed before that window closes. The window is wall-clock based (context.WithTimeout / time.After).

1.2 Why a second heavy process breaks it

1.3 Why the isolated PASS proves nothing

-run in isolation removes the contention, so it passes by construction. A single isolated PASS is consistent with both healthy code and a flaky assertion, so it cannot decide the question. Recorded as information only.

1.4 Why import linkage settles it mechanically

The changed package was src/ident; the failing package is cmd/dagger. If the failing package does not import the changed package (directly or transitively), no change can alter its behaviour. The regression hypothesis dies on the dependency graph, independent of any test run.

$ go list -deps ./cmd/dagger | grep -E '/src/ident$' ; echo "exit=$?"
exit=1          # zero matches → zero import linkage → impossible regression

1.5 Evidence (<project>, tick #549)

Run Condition Result
HEAD, full suite under concurrent agent load FAIL 17.3s + 11.7s
HEAD, single test -run isolated PASS 4.2s
Parent commit, full suite idle box PASS 312s
HEAD, full suite idle box PASS 258s
go list -deps cmd/dagger static no src/ident dependency

Both parent and HEAD are green on an idle box; only HEAD-under-load fails; there is no import linkage. The probability this is a regression is effectively zero.


2. Disambiguation protocol

Pitfall: a "supposedly idle" re-run can still overlap a background judge/worker. Enumerate background processes and check load average before trusting any result.

Step 0 — prove the box is idle

nproc
uptime
cat /proc/loadavg
ps -eo pid,pcpu,pmem,etimes,comm,args --sort=-pcpu | head -n 25
pgrep -af 'go test|go build|compile|link|judge|worker|agent' || echo "no competing processes"
# cgroup CPU throttling (containers / systemd slices):
cat /sys/fs/cgroup/cpu.stat 2>/dev/null | grep -E 'nr_throttled|throttled_usec'

Authoritative-idle rule: 1-min load < nproc and no competing go test/judge/worker process. Otherwise wait or isolate the run in a cgroup/slice.

Step 1 — isolated single test (informational only)

go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/

Step 2 — import-linkage check (kills the regression hypothesis)

go list -deps ./cmd/dagger | grep -E '/src/ident$' \
  && echo "linkage exists — investigate" \
  || echo "NO LINKAGE — changed package cannot affect the failing package"

Zero output ⇒ regression mechanically impossible; stop and file a flake row.

Step 3 — full suite at parent and HEAD on a verified-idle box

for rev in "$(git rev-parse HEAD~1)" "$(git rev-parse HEAD)"; do
  wt=$(mktemp -d); git worktree add --detach "$wt" "$rev" >/dev/null
  ( cd "$wt" && go test -race -count=1 ./pkg/ )
  git worktree remove --force "$wt"
done

Both green on idle + Step 2 empty ⇒ load-contention flake, not a regression.


3. Exact fix

F1 — Harden the test so it measures retry logic, not the scheduler

  1. Confirm server reachability before starting the deadline clock.
  2. Scale the deadline by observed machine pressure.
  3. Emit timing diagnostics on failure.
// testDeadline scales a nominal deadline by current scheduler pressure so the test
// measures retry behaviour rather than the CI box's CPU contention.
func testDeadline(t *testing.T, base time.Duration) time.Duration {
    t.Helper()
    // Explicit override wins (CI can set 1.0; stress runs can set 5.0).
    if v := os.Getenv("DAGGER_TEST_DEADLINE_MULT"); v != "" {
        if m, err := strconv.ParseFloat(v, 64); err == nil && m > 0 {
            return time.Duration(float64(base) * m)
        }
    }
    // /proc/loadavg is cheap and Linux-only; fall back to base elsewhere.
    raw, err := os.ReadFile("/proc/loadavg")
    if err != nil {
        return base
    }
    fields := strings.Fields(string(raw))
    if len(fields) == 0 {
        return base
    }
    load, err := strconv.ParseFloat(fields[0], 64)
    if err != nil {
        return base
    }
    cores := float64(runtime.NumCPU())
    if mult := load / cores; mult > 1 {
        t.Logf("load1=%.2f cores=%.0f → deadline x%.2f", load, cores, mult)
        return time.Duration(float64(base) * mult)
    }
    return base
}

// waitServerReady blocks until the test server accepts connections, so the
// reachability clock starts only once the server is actually serving.
func waitServerReady(t *testing.T, addr string) {
    t.Helper()
    require.Eventually(t, func() bool {
        c, err := net.DialTimeout("tcp", addr, 200*time.Millisecond)
        if err != nil {
            return false
        }
        _ = c.Close()
        return true
    }, 30*time.Second, 50*time.Millisecond, "test server never became reachable at %s", addr)
}

func TestExecuteRetryAfterNodeDeadlineDoesNotCollide(t *testing.T) {
    srv, addr := startTestServer(t) // existing helper
    defer srv.Close()

    waitServerReady(t, addr) // <- start the clock only after readiness

    deadline := testDeadline(t, 2*time.Second) // was a fixed 2s (or shorter)
    ctx, cancel := context.WithTimeout(context.Background(), deadline)
    defer cancel()

    start := time.Now()
    _, err := client.Execute(ctx, addr, /* ... */)
    if err != nil {
        t.Fatalf("attempt 1 never reached the server after %s (deadline %s, load-scaled): %v",
            time.Since(start), deadline, err)
    }
    // ... existing retry/collision assertions ...
}

Checklist:

This does not weaken intent — readiness is a hard precondition and dispatch is still asserted, so a genuinely dead server still fails.

F2 — Isolate the suite from co-tenant workloads

# Package-level serialisation + bounded intra-package parallelism.
go test -race -count=1 -p 1 -parallel 2 ./pkg/...
systemd-run --scope --user \
  -p AllowedCPUs=0-3 -p CPUQuota=300% \
  go test -race -count=1 ./pkg/...

CI hygiene: always -count=1; generous -timeout; run judge/worker in a separate cgroup/slice; never run two -race suites on the same cores.

F3 — File the flake row

id: DAGGER-0959
test: TestExecuteRetryAfterNodeDeadlineDoesNotCollide
class: go-test-race-full-suite-fails-only-under-concurrent-load
status: open
evidence:
  head_under_load_fail: "17.3s, 11.7s"
  head_isolated_pass: "4.2s"
  parent_idle_pass: "312s"
  head_idle_pass: "258s"
  import_linkage: "cmd/dagger does not import src/ident"
resolution: >
  Flake under CPU contention. Harden deadline scaling + server-readiness wait (F1),
  isolate race suite (F2). Do not reject the landed commit.

4. Verification

4.1 Positive reproduction (proves contention)

stress-ng --cpu "$(nproc)" --timeout 180s &
# or: for i in $(seq "$(nproc)"); do ( yes >/dev/null & ); done
LOAD_PIDS=$(jobs -p)

go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/

kill $LOAD_PIDS 2>/dev/null; wait 2>/dev/null

4.2 Verify the fix survives the same load

for i in $(seq "$(nproc)"); do ( yes >/dev/null & ); done
LOAD_PIDS=$(jobs -p)
go test -race -count=1 -run '^TestExecuteRetryAfterNodeDeadlineDoesNotCollide$' -v ./pkg/
kill $LOAD_PIDS 2>/dev/null; wait 2>/dev/null

4.3 Verify no intent was weakened

Kill the test server / point the client at a dead port; the hardened test must still FAIL.

4.4 Full-suite sign-off

cat /proc/loadavg; nproc
go test -race -count=1 -p 1 -parallel 2 ./pkg/...      # must be green

4.5 Regression closure

go list -deps ./cmd/dagger | grep -E '/src/ident$' && echo "linkage" || echo "no linkage"
# expected: no linkage

Pass criteria: 4.1 reproduces under load, 4.2 passes under the same load, 4.3 still fails on a dead server, 4.4 green idle, 4.5 no linkage.


5. One-line rule of thumb

A timing-sensitive -race test that fails only when a second heavy process is running, whose failing package does not import the changed package, and that is green at both parent and HEAD on a verified-idle box, is a load-contention flake. Harden the deadline and isolate the suite; do not reject the commit.


Appendix A — one-shot triage script

/workspace/solution/triage-go-flake.sh runs Section 2 end-to-end:

./triage-go-flake.sh ./pkg/ TestExecuteRetryAfterNodeDeadlineDoesNotCollide src/ident HEAD~1 HEAD

It checks idle state and competing processes (Step 0), prints import linkage (Step 2), runs the isolated test (Step 1), and runs the full suite at parent and HEAD in isolated worktrees (Step 3). It fails closed if load1 >= nproc, refusing to present a non-idle result as authoritative.

Evidence & signatures

# Evidence
- Problem class: go-test-race-full-suite-fails-only-under-concurrent-load
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T15:38:53.528Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Symptom: a timing-sensitive Go test fails inside a full-package `go test -race` run with a reachability/deadline error, but ONLY while a second heavy process (another -race suite, an LLM judge/worker agent shelling out) shares the box; the same commit passes the full suite on an idle box. Diagnosis recipe proven in <project> tick #549: (1) re-run the single test with -run in isolation \u2014 a PASS proves nothing structural either way; (2) grep whether the failing package even imports the changed package \u2014 zero import linkage kills the regression hypothesis mechanically; (3) run the FULL suite at the parent commit and at HEAD on a truly idle box \u2014 both green means load-contention flake, not a regression. Pitfall: a supposedly idle re-run can still overlap a background judge/worker; enumerate background processes before trusting the result. Resolution: file a flake row (<project> DAGGER-0959) instead of rejecting the landed commit.", "environment": "linux, go test -race -count=1 ./pkg/, shared dev box with concurrent agent workloads", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-test-race-full-suite-fails-only-under-concurrent-load", "provider": "openrouter", "solved_at": "2026-09-19T15:38:53.528Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog