t8y2/dbx · error
close startup warmup %s: %w
Error message
close startup warmup %s: %w
What it means
This panic wraps an error from process.close() during the startup warm-up loop. close() sends a JSON-RPC 'shutdown' request, closes stdin, and waits for the child process; it returns the shutdown-call error if present, otherwise the cmd.Wait() error. A failure here means the agent refused/failed the shutdown RPC or exited abnormally (non-zero status, signal kill), which the harness treats as a broken environment and aborts the benchmark.
Source
Thrown at agents/drivers/rabbitmq/bench/agent_compare.go:156
}
func benchmarkStartups(agents []agentSpec, warmups, iterations int) []benchmarkResult {
for warmup := 0; warmup < warmups; warmup++ {
order := agents
if warmup%2 == 1 {
order = []agentSpec{agents[1], agents[0]}
}
for _, agent := range order {
process, _, err := startAgent(agent.Command)
if err != nil {
panic(fmt.Errorf("warm up startup %s: %w", agent.Name, err))
}
if _, err := process.call("handshake", map[string]any{}); err != nil {
process.kill()
panic(fmt.Errorf("warm up handshake %s: %w", agent.Name, err))
}
if err := process.close(); err != nil {
panic(fmt.Errorf("close startup warmup %s: %w", agent.Name, err))
}
}
}
readySamples := map[string][]float64{}
handshakeSamples := map[string][]float64{}
rssSamples := map[string][]int64{}
readyDurations := map[string]time.Duration{}
handshakeDurations := map[string]time.Duration{}
for iteration := 0; iteration < iterations; iteration++ {
order := agents
if iteration%2 == 1 {
order = []agentSpec{agents[1], agents[0]}
}
for _, agent := range order {
process, readyDuration, err := startAgent(agent.Command)
if err != nil {
panic(fmt.Errorf("start %s: %w", agent.Name, err))View on GitHub (pinned to c0390bff16)
Solutions
- Check agent stderr for why it exited non-zero; fix the agent's shutdown/cleanup path so it exits 0 after replying to 'shutdown'.
- If the agent intentionally exits on stdin EOF before replying, either reply to shutdown first in the agent, or treat stdin-close as the shutdown signal in the harness.
- In close(), ignore the shutdown-call error and report only the Wait() error, since a dead-but-reaped child is acceptable at end of warm-up.
- Verify no external supervisor/oom-killer is killing children during the run.
- Replace panic with an error return so warm-up failures degrade gracefully.
Example fix
// before
if err := process.close(); err != nil {
panic(fmt.Errorf("close startup warmup %s: %w", agent.Name, err))
}
// after
if err := process.close(); err != nil {
log.Printf("warmup close failed for %s: %v", agent.Name, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: agent should exit 0 after a shutdown RPC
stdin, _ := cmd.StdinPipe()
cmd.Start()
fmt.Fprintf(stdin, "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"shutdown\",\"params\":{}}\n")
stdin.Close()
if err := cmd.Wait(); err != nil {
log.Fatalf("agent does not shut down cleanly: %v", err)
} Type guard
func isExitStatus(err error) bool {
var exitErr *exec.ExitError
return errors.As(err, &exitErr)
}
func isKilled(err error) bool {
return err != nil && strings.Contains(err.Error(), "signal: killed")
} Try / catch
func safeClose(p *agentProcess, name string) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("close startup warmup %s: %v", name, r)
}
}()
return p.close()
}
// Caller: log and continue for warmups; only fatal if Wait also failed. Prevention
- Make the agent reply to the shutdown RPC before exiting, and exit with status 0.
- Do not treat stdin EOF as an excuse to skip the shutdown reply.
- Test agent shutdown as part of CI so regressions surface early.
- Distinguish shutdown RPC errors from Wait() errors in close() to ease diagnosis.
- Log the child's exit code and signal on close failure.
When it happens
Trigger: In benchmarkStartups warm-up: after a successful handshake, process.close() fails — the 'shutdown' RPC write/read fails ('agent response unavailable'), or command.Wait() returns an error such as 'exit status 1' or 'signal: killed', indicating the agent did not shut down cleanly.
Common situations: The agent binary handles 'shutdown' but exits non-zero (e.g. logs an error on cleanup); the agent exits immediately on stdin close before replying to shutdown, so the call errors; Wait() reports 'signal: killed' because an external watchdog/oom-killer terminated the JVM; a buggy agent version changed the shutdown semantics.
Related errors
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/f4dde0995384c123.
Report an issue: GitHub.