t8y2/dbx · error · errAgentSessionLimit

%w: %d

Error message

%w: %d

What it means

The Xugu agent driver caps concurrent agent sessions at maxAgentSessions (256). openSession checks the session map before dialing the database and returns a wrapped errAgentSessionLimit ('agent session limit reached') with the current count when capacity is exhausted. The sentinel is classified as a retryable resource error because the check happens before any DB work starts.

Source

Thrown at agents/drivers/xugu/main.go:855

	session, err := r.session(agentSessionID)
	if err != nil {
		return nil, false, err
	}
	// Database, schema, transaction, and cursor state are connection-scoped.
	session.mu.Lock()
	defer session.mu.Unlock()
	return session.server.dispatch(method, params)
}

func (r *runtimeServer) openSession(agentSessionID string, params connectParams) error {
	r.mu.Lock()
	if _, exists := r.sessions[agentSessionID]; exists {
		r.mu.Unlock()
		return fmt.Errorf("agent session already exists: %s", agentSessionID)
	}
	if len(r.sessions) >= maxAgentSessions {
		r.mu.Unlock()
		return fmt.Errorf("%w: %d", errAgentSessionLimit, maxAgentSessions)
	}
	r.mu.Unlock()

	server := newServer()
	// APP_NAME is useful for identifying a business session from SYS_SESSIONS,
	// but some Xugu server/driver combinations close the socket when an ordinary
	// user sends this optional login attribute. Keep the original parameters for
	// the permission-degraded path and add APP_NAME only when SYSTEM control is
	// actually available.
	businessParams := params
	if !xuguControlSessionEligible(params) {
		r.connectMu.Lock()
		_, err := server.connectWithControl(businessParams, nil, false)
		r.connectMu.Unlock()
		if err != nil {
			return err
		}
		return r.registerSession(agentSessionID, server, "")

View on GitHub (pinned to c0390bff16)

Solutions

  1. Close idle sessions with close_session/disconnect so len(r.sessions) drops below 256, then retry.
  2. Restart the agent process to clear all in-memory sessions if ownership of leaked sessions is unclear.
  3. Retry the open later — the error is classified Retryable=true, category=resource, because no DB operation had started.
  4. Audit the client for unbalanced open/close calls; fix the leak rather than raising the limit.

Example fix

// before (leaking sessions)
for _, q := range queries {
  id := openSession(connStr) // never closed -> hits 256 cap
  run(id, q)
}
// after
defer closeSession(id)
run(id, q)
Defensive patterns

Strategy: retry

Validate before calling

// client-side bookkeeping before calling open_session
if activeSessions >= 256 {
  return fmt.Errorf("local guard: %d sessions open, close some first", activeSessions)
}

Try / catch

if err := openSession(); err != nil {
  if strings.Contains(err.Error(), "agent session limit reached") {
    time.Sleep(backoff)
    retry() // classified retryable/resource
  }
}

Prevention

When it happens

Trigger: Calling open_session (or any flow through runtimeServer.openSession) when len(r.sessions) already equals maxAgentSessions=256, e.g. 256 prior sessions were opened and never closed.

Common situations: Client leaks sessions by opening repeatedly without close_session; a hung agent process accumulates sessions; load tests open more than 256 parallel connections; reconnect storms after network blips leave stale sessions registered.

Related errors


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