t8y2/dbx · error

close %s: %w

Error message

close %s: %w

What it means

This panic wraps an error from process.close() after a measured startup iteration. close() performs the 'shutdown' RPC, closes stdin, then cmd.Wait(); the returned error is either the shutdown RPC failure or an abnormal child exit reported by Wait. In the measured path this aborts the whole benchmark because remaining iterations cannot trust the agent lifecycle.

Source

Thrown at agents/drivers/rabbitmq/bench/agent_compare.go:191

			if err != nil {
				panic(fmt.Errorf("start %s: %w", agent.Name, err))
			}
			handshakeStart := time.Now()
			if _, err := process.call("handshake", map[string]any{}); err != nil {
				process.kill()
				panic(fmt.Errorf("handshake %s: %w", agent.Name, err))
			}
			handshakeDuration := time.Since(handshakeStart)
			readySamples[agent.Name] = append(readySamples[agent.Name], milliseconds(readyDuration))
			handshakeSamples[agent.Name] = append(
				handshakeSamples[agent.Name],
				milliseconds(readyDuration+handshakeDuration),
			)
			rssSamples[agent.Name] = append(rssSamples[agent.Name], readRSSKB(process.command.Process.Pid))
			readyDurations[agent.Name] += readyDuration
			handshakeDurations[agent.Name] += readyDuration + handshakeDuration
			if err := process.close(); err != nil {
				panic(fmt.Errorf("close %s: %w", agent.Name, err))
			}
		}
	}

	results := make([]benchmarkResult, 0, len(agents)*2)
	for _, agent := range agents {
		artifactBytes := fileSize(agent.ArtifactPath)
		ready := summarize(agent.Name, "startup_ready", 0, readySamples[agent.Name], readyDurations[agent.Name], 0)
		ready.ReadyRSSKB = medianInt64(rssSamples[agent.Name])
		ready.ArtifactBytes = artifactBytes
		results = append(results, ready)
		withHandshake := summarize(
			agent.Name,
			"startup_handshake",
			0,
			handshakeSamples[agent.Name],
			handshakeDurations[agent.Name],
			0,

View on GitHub (pinned to c0390bff16)

Solutions

  1. Check agent stderr for the teardown error and fix the agent's shutdown path to reply then exit 0.
  2. If the agent exits on stdin close by design, change close() to send shutdown best-effort and only fail on a Wait() error.
  3. Relax Wait() error handling: treat ordinary non-zero exits at shutdown as non-fatal (log only) since samples were already collected.
  4. Confirm nothing external (docker healthchecks, oom-killer, CI timeouts) kills children mid-run.
  5. Replace the panic with an error return so one bad close does not discard the entire run.

Example fix

// before
if err := process.close(); err != nil {
	panic(fmt.Errorf("close %s: %w", agent.Name, err))
}
// after
if err := process.close(); err != nil {
	log.Printf("close %s: %v", agent.Name, err)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Prefer graceful shutdown; only treat real Wait() failures as fatal
err := process.close()
var exitErr *exec.ExitError
if err != nil && !errors.As(err, &exitErr) {
	log.Fatalf("unexpected close failure: %v", err)
}
// Non-zero exits at teardown are logged, not fatal, since samples were collected.

Type guard

func isBenignCloseError(err error) bool {
	var exitErr *exec.ExitError
	if errors.As(err, &exitErr) {
		return true
	}
	return err != nil && strings.Contains(err.Error(), "agent response unavailable")
}

Try / catch

func safeClose(p *agentProcess, name string) {
	defer func() { _ = recover() }()
	if err := p.close(); err != nil {
		log.Printf("close %s: %v", name, err)
	}
}
// Fallback: if shutdown RPC failed, force-kill so no orphans remain.
// if err != nil { process.kill() }

Prevention

When it happens

Trigger: In benchmarkStartups measured loop: after sampling ready/handshake/RSS, process.close() fails — the shutdown request write/read fails ('agent response unavailable: ...' because the agent already exited), or Wait() returns 'exit status N' (non-zero) or 'signal: killed'.

Common situations: Agent exits non-zero during teardown (cleanup error, failed broker disconnect); agent treats stdin EOF as exit and never answers shutdown, making callError non-nil; oom-killer or timeout watchdog kills the JVM; agent version regression changed shutdown reply format so the harness errors on the response.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/aba485614496d365. Report an issue: GitHub.