chenhg5/cc-connect · error

did not respond within %s

Error message

did not respond within %s

What it means

Sent to notifySessionCloseFailure when Close() on an agent session exceeds closeTimeout and the close is abandoned. The session is marked unsafe-to-resume and the owning chat is alerted, because the underlying process may still be running.

Source

Thrown at core/engine.go:4613

	case <-done:
		if closeErr != nil {
			slog.Error("agent session close reported failure, process may still be running",
				"session", sessionKey, "error", closeErr)
			// The old process may still hold this conversation open — the
			// next turn must not resume into it.
			e.markUnsafeResume(sessionKey)
			e.notifySessionCloseFailure(sessionKey, platform, replyCtx, closeErr)
			return
		}
		if elapsed := time.Since(closeStart); elapsed >= slowAgentClose {
			slog.Warn("slow agent session close", "elapsed", elapsed, "session", sessionKey)
		}
	case <-time.After(closeTimeout):
		slog.Error("agent session close timed out, abandoning",
			"timeout", closeTimeout, "session", sessionKey)
		e.markUnsafeResume(sessionKey)
		e.notifySessionCloseFailure(sessionKey, platform, replyCtx,
			fmt.Errorf("did not respond within %s", closeTimeout))
	}
}

// notifySessionCloseFailure alerts the chat that owned a session when its
// underlying process could not be confirmed killed. Without this, a stuck
// process can keep running in the background — still holding the session's
// credentials — while the user believes /stop (or /new) already ended it.
func (e *Engine) notifySessionCloseFailure(sessionKey string, platform Platform, replyCtx any, cause error) {
	if platform == nil || replyCtx == nil {
		slog.Error("agent session close failed and no chat is available to alert",
			"session", sessionKey, "cause", cause)
		return
	}
	text := e.i18n.T(MsgSessionCloseFailed) + fmt.Sprintf(" (%v)", cause)
	if err := e.waitOutgoing(platform); err != nil {
		slog.Warn("notifySessionCloseFailure: wait outgoing failed", "session", sessionKey, "error", err)
	}
	if err := platform.Send(e.ctx, replyCtx, text); err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Force-kill the leaked agent process manually (pkill the CLI binary)
  2. Investigate why the agent CLI hangs on Close (child process reaping, stdin/stdout not closing)
  3. Treat the session as unsafe — do not resume it; start a fresh session
  4. Increase closeTimeout if the agent legitimately needs longer, though leaking is the real issue

Example fix

// before
closeTimeout := 10 * time.Second // too short for slow agent teardown
// after
closeTimeout := 130 * time.Second // or handle abandon + pkill path deliberately
Defensive patterns

Strategy: retry

Try / catch

engine.OnSessionCloseFailure(func(key string, err error) { if strings.Contains(err.Error(), "did not respond within") { pkillAgentProcess(key); markSessionUnsafe(key) } })

Prevention

When it happens

Trigger: agentSession.Close() blocks longer than closeTimeout (the comment mentions up to 130s hangs); time.After fires before Close returns.

Common situations: Agent CLI hangs on shutdown (waiting on child processes, stuck network call); SIGKILL-ignoring process state; resource exhaustion in the agent process.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/6e0db05236d42d44. Report an issue: GitHub.