Why
Three places drop an error and carry on, and each turns a diagnosable failure into a
puzzling one later.
| where |
dropped |
what the operator sees instead |
internal/agent/agent.go:34-39 |
Listen(sockDir) |
no control host channel available from a primitive, much later |
internal/transport/local.go:31-38 |
os.MkdirTemp |
the same, on the local transport |
internal/agent/channel.go |
the previous conn is replaced without Close |
nothing — a file descriptor leaks per reconnection |
The first two share a shape: if err == nil { … } with no else. The third is not a dropped
error but a dropped resource, on a path built for repetition — Accept loops so a
reconnecting control host replaces the connection, and an agent lives up to two hours.
Honest about provenance
The Listen one was confirmed during a review two sessions ago and never filed. That is
the failure this issue also records: a verified defect that stayed in a conversation instead
of becoming an issue, which is precisely what CLAUDE.md's issue-handling rule exists to
prevent.
Build
- Close the previous connection when a new bridge replaces it.
- Report the two swallowed errors rather than continuing silently. The agent has no channel
to report on at that point, so the honest outcome is a failure naming the cause — a job
that cannot open its channel will fail on its first ~file.read anyway, and the message
should say why.
- Whether a channel that cannot be opened should fail the job immediately or lazily is the
decision to take here: failing late is what happens today, and it is defensible for a plan
that never asks the control host for anything.
Validation
- A failing test first for the leak: two successive bridges, asserting the first connection
is closed. internal/agent/bridge_reconnect_test.go already drives reconnection.
- A test that a workdir that cannot be created produces an error naming it.
go test ./... and the e2e suite green — the bridge path is exercised by the harness.
Why
Three places drop an error and carry on, and each turns a diagnosable failure into a
puzzling one later.
internal/agent/agent.go:34-39Listen(sockDir)no control host channel availablefrom a primitive, much laterinternal/transport/local.go:31-38os.MkdirTempinternal/agent/channel.goconnis replaced withoutCloseThe first two share a shape:
if err == nil { … }with no else. The third is not a droppederror but a dropped resource, on a path built for repetition —
Acceptloops so areconnecting control host replaces the connection, and an agent lives up to two hours.
Honest about provenance
The
Listenone was confirmed during a review two sessions ago and never filed. That isthe failure this issue also records: a verified defect that stayed in a conversation instead
of becoming an issue, which is precisely what CLAUDE.md's issue-handling rule exists to
prevent.
Build
to report on at that point, so the honest outcome is a failure naming the cause — a job
that cannot open its channel will fail on its first
~file.readanyway, and the messageshould say why.
decision to take here: failing late is what happens today, and it is defensible for a plan
that never asks the control host for anything.
Validation
is closed.
internal/agent/bridge_reconnect_test.goalready drives reconnection.go test ./...and the e2e suite green — the bridge path is exercised by the harness.