t8y2/dbx · error
agent session limit reached: {MAX_AGENT_SESSIONS}
Error message
agent session limit reached: {MAX_AGENT_SESSIONS} What it means
open_session enforces a cap of MAX_AGENT_SESSIONS concurrently open sessions using an OwnedSemaphorePermit per session (the permit is stored in AgentSession::_slot and released when the session is closed/dropped). try_acquire_owned() fails when all permits are held, so the runtime refuses to open another session with this error. It is classified as a 'resource' error, retryable=true, session_disposition 'keep'.
Source
Thrown at agents/drivers/tdengine/src/runtime.rs:239
}
}
}
async fn open_session(&self, id: &str, params: ConnectParams) -> Result<()> {
if id.trim().is_empty() {
bail!("agentSessionId is required");
}
{
let sessions = self.sessions.read().await;
if sessions.contains_key(id) {
bail!("agent session already exists: {id}");
}
}
let slot = self
.session_slots
.clone()
.try_acquire_owned()
.map_err(|_| anyhow!("agent session limit reached: {MAX_AGENT_SESSIONS}"))?;
let mut driver = TdengineDriver::new();
driver.connect(params).await?;
let session = Arc::new(AgentSession {
driver: Mutex::new(driver),
active: StdMutex::new(None),
next_operation_id: AtomicU64::new(1),
_slot: slot,
});
let mut sessions = self.sessions.write().await;
if sessions.contains_key(id) {
bail!("agent session already exists: {id}");
}
sessions.insert(id.to_string(), session);
Ok(())
}
async fn session(&self, id: &str) -> Result<Arc<AgentSession>> {
self.sessions.read().await.get(id).cloned().ok_or_else(|| anyhow!("agent session not found: {id}"))View on GitHub (pinned to c0390bff16)
Solutions
- Call close_session (or disconnect) for sessions no longer in use before opening new ones — permits are freed when sessions close
- Reuse an existing session id: the error is retryable and sessions are kept, so retry after closing one, or reconnect to a live agentSessionId
- Restart the agent process (or send 'shutdown') to clear all leaked sessions and free all slots
- Audit the client for session leaks — every open_session must have a matching close_session, including on error paths
Example fix
// before: leak — new session per query, never closed
for q in queries {
send({"method":"open_session","params":{"agentSessionId": format!("s-{}", n), ...}});
run(q);
}
// after: close each session when done
for q in queries {
send(open_session(id));
run(q);
send({"method":"close_session","params":{"agentSessionId": id}});
} Defensive patterns
Strategy: validation
Validate before calling
const MAX_SESSIONS = 8; // must not exceed the agent's MAX_AGENT_SESSIONS
const openSessions = new Set();
function canOpenSession(id) {
return !openSessions.has(id) && openSessions.size < MAX_SESSIONS;
}
if (!canOpenSession(id)) throw new Error("close an existing session before opening a new one"); Type guard
function isSessionLimitError(res) {
return res?.error?.data?.category === "resource"
&& /session limit reached/i.test(res.error?.message ?? "");
} Try / catch
try {
await sendRpc({ method: "open_session", params });
} catch (res) {
if (isSessionLimitError(res)) {
const oldest = oldestOpenSession();
await sendRpc({ method: "close_session", params: { agentSessionId: oldest } });
await sendRpc({ method: "open_session", params }); // retryable=true, safe to retry
} else { throw res; }
} Prevention
- Pair every open_session with a close_session/disconnect in a finally block, including on error paths
- Track open agentSessionIds client-side and reuse sessions instead of opening new ones per query
- Retry with backoff when the structured error reports retryable=true and session_disposition=keep
- Send 'shutdown' or restart the agent when session state is suspected to be leaked after a client crash
When it happens
Trigger: Calling open_session (or the legacy 'connect' method, which routes to open_session under LEGACY_SESSION_ID) when MAX_AGENT_SESSIONS sessions are already open and not closed; leaked sessions from prior connections that were never closed with close_session/disconnect.
Common situations: A client that opens a new agentSessionId per query without closing previous ones; app reconnect loops creating sessions after network blips while old sessions linger; a driver upgrade/restart of the host that lost track of session ids but left the agent process running; multi-connection tooling exceeding the configured session budget.
Related errors
- agent request capacity is temporarily exhausted
- Agent session limit reached: <MAX_SESSIONS>
- agent operation capacity is temporarily exhausted
- agent operation capacity is temporarily exhausted
- Agent session limit reached: %d
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/d5c82e9ece71f4ee.
Report an issue: GitHub.