Skip to content

flake: Test process crash - NATS peer refresh after shutdown #1631

Closed

Description

@flake-investigator

CI failure

The failure occurred in the same time window as the CI alert. The complete 2,037-line failing-job log was available and reviewed.

Failure evidence

The coderd/x/nats test process crashed, causing 11 tests/subtests to be reported as (unknown). These are crash fallout, not 11 independent test failures.

=== FAIL: coderd/x/nats TestPubsub_ClusterTLS/RotationOverlap (unknown)
panic: send on closed channel

goroutine 1439 [running]:
github.com/nats-io/nats-server/v2/server.(*Server).reloadAuthorization(...)
    .../github.com/nats-io/nats-server/v2@v2.14.2/server/reload.go:2298
github.com/nats-io/nats-server/v2/server.(*Server).applyOptions(...)
    .../github.com/nats-io/nats-server/v2@v2.14.2/server/reload.go:2050
github.com/nats-io/nats-server/v2/server.(*Server).ReloadOptions(...)
    .../github.com/nats-io/nats-server/v2@v2.14.2/server/reload.go:1474
github.com/coder/coder/v2/coderd/x/nats.(*Pubsub).setPeerAddresses(...)
    /home/runner/work/coder/coder/coderd/x/nats/cluster.go:131
github.com/coder/coder/v2/coderd/x/nats.(*Pubsub).runPeerRefresh(...)
    /home/runner/work/coder/coder/coderd/x/nats/cluster.go:84
created by github.com/coder/coder/v2/coderd/x/nats.New in goroutine 361
    /home/runner/work/coder/coder/coderd/x/nats/pubsub.go:420

Immediately before the panic, test cleanup logged nats server shut down. Other affected (unknown) results include TestPubsub_ClusterTLS, Mesh, SANMismatch, MixedTLSAndPlaintext, WrongCARejected, TestPubsub_ClusterTLS_CacheSwap, and TestPubsub_ClusterTLS_RealCA.

Error analysis / root cause

Classification: process crash caused by a code-level shutdown race.

New starts go p.runPeerRefresh(). Close cancels p.ctx, closes connections, and calls p.Server.Shutdown() / WaitForShutdown(), but does not join the peer-refresh goroutine or synchronize server shutdown with clusterMu.

setPeerAddresses checks p.ctx.Err() while holding clusterMu, then later calls p.Server.ReloadOptions. A refresh that passes the context check just before cancellation can therefore enter ReloadOptions while Close shuts down the NATS server. NATS reloadAuthorization then sends on a server channel that shutdown has already closed.

Likely fix direction: track/join runPeerRefresh before shutting down the embedded server, or otherwise serialize cancellation/server shutdown against the whole setPeerAddresses/ReloadOptions critical section.

No Go race-detector warning was present (WARNING: DATA RACE / race detected during execution of test). No OOM, signal: killed, allocation failure, disk exhaustion, or file-descriptor exhaustion indicator was present.

Assignment analysis

Blame/history targets:

git blame -L 120,317 coderd/x/nats/tls_internal_test.go
git blame -L 72,135 coderd/x/nats/cluster.go
git blame -L 405,423 coderd/x/nats/pubsub.go
git log --oneline -10 --follow coderd/x/nats/tls_internal_test.go
git log --oneline -20 -- coderd/x/nats/cluster.go
git log --oneline -10 --follow coderd/x/nats/pubsub.go

The failing cluster-TLS test file has one substantive commit: ad29777 (feat: NATS mTLS pubsub implementation, PR #26902), authored by cstyan. That same commit is the most recent substantive modifier of the crashing peer-refresh implementation and Pubsub lifecycle code. Assignment is therefore based on test-function and implementation ownership, not on the author of the failing CI commit.

Assignee: cstyan.

Duplicate search

Searched open and closed coder/internal issues, including the last 30 days, for:

  • TestPubsub_ClusterTLS, TestPubsub_ClusterTLS/RotationOverlap, and the test family
  • send on closed channel
  • reloadAuthorization, ReloadOptions, and runPeerRefresh
  • coderd/x/nats, tls_internal_test.go, NATS shutdown, panic, process crash, and unknown failures
  • data-race and OOM signatures

No matching issue was found. Related NATS flakes are different failure modes: #1617, #1607, #1612, and #1552.

Reproduction

The race is timing-dependent. Stress the parallel cluster-TLS cleanup path:

go test ./coderd/x/nats -run 'TestPubsub_ClusterTLS($|_)' -count=100

A focused regression test should force a peer refresh to pause after the context check, invoke Close, then release the refresh and verify that shutdown waits without calling ReloadOptions on a stopped server.

Activity

  1. linear-code commented on Jul 28, 2026

    @linear-code
  2. assigned and unassigned on Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions