t8y2/dbx · error

Agent session already exists: %s

Error message

Agent session already exists: %s

What it means

The runtime server refuses to create a new agent session because a session with the same ID is already registered in r.sessions. This guard prevents accidentally clobbering live sessions (their etcd connections and watches) by a second openSession with a duplicate ID. Callers must close or reuse the existing session instead.

Source

Thrown at agents/drivers/etcd-go/main.go:259

		if err != nil {
			return nil, false, err
		}
		session.mu.Lock()
		defer session.mu.Unlock()
		result, err := session.state.handle(method, params)
		return result, false, err
	}
}

func requiredSessionID(params map[string]json.RawMessage) string {
	return strings.TrimSpace(stringParam(params, "agentSessionId"))
}

func (r *runtimeServer) openSession(id string, params map[string]json.RawMessage) (any, bool, error) {
	r.mu.Lock()
	if _, exists := r.sessions[id]; exists {
		r.mu.Unlock()
		return nil, false, fmt.Errorf("Agent session already exists: %s", id)
	}
	if len(r.sessions) >= maxAgentSessions {
		r.mu.Unlock()
		return nil, false, fmt.Errorf("Agent session limit reached: %d", maxAgentSessions)
	}
	session := &agentSession{state: newEtcdSession()}
	r.sessions[id] = session
	r.mu.Unlock()

	if _, err := session.state.connect(params); err != nil {
		r.mu.Lock()
		delete(r.sessions, id)
		r.mu.Unlock()
		session.state.close()
		return nil, false, err
	}
	return map[string]bool{"ok": true}, false, nil
}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Close the existing session first (call the close/shutdown method for that id) and retry openSession
  2. Use a fresh unique session id (UUID) for each openSession call
  3. Track session ids client-side and treat 'already exists' as 'session is live' — reuse it instead of reopening

Example fix

// before
client.call("open", map[string]any{"id": "agent-1"})
client.call("open", map[string]any{"id": "agent-1"}) // panics with duplicate

// after
if _, err := client.call("open", map[string]any{"id": id}); err != nil {
    client.call("close", map[string]any{"id": id})
    client.call("open", map[string]any{"id": id})
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check the id is fresh before opening (best-effort; server is authoritative)
if _, err := runtime.Call("get", map[string]any{"id": id}); err == nil {
    return fmt.Errorf("session %s appears to already exist", id)
}

Try / catch

_, err := runtime.Call("open", map[string]any{"id": id})
if err != nil && strings.Contains(err.Error(), "already exists") {
    runtime.Call("close", map[string]any{"id": id})
    _, err = runtime.Call("open", map[string]any{"id": id})
}

Prevention

When it happens

Trigger: Calling the runtime 'open' method (routed to runtimeServer.openSession) with an id already present in r.sessions while the previous session was never closed.

Common situations: Reconnecting a client after a dropped RPC without closing the old session; reusing a hard-coded session ID in scripts/tests; two clients sharing the same session ID; retry logic re-issuing open after a timeout that actually succeeded.

Related errors


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