{"record":{"id":"314de0eec4e610bb","repo":"t8y2/dbx","slug":"agent-session-limit-reached","errorCode":null,"errorMessage":"agent session limit reached","messagePattern":"agent session limit reached","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/xugu/protocol_error.go","lineNumber":17,"sourceCode":"package main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\terrAgentSessionLimit     = errors.New(\"agent session limit reached\")\n\terrAgentSessionNotFound  = errors.New(\"agent session not found\")\n\terrXuguOperationTimeout  = errors.New(\"xugu operation timed out\")\n\terrXuguOperationCanceled = errors.New(\"xugu operation canceled\")\n\n\t// go-xugu-driver exposes server errors as plain strings rather than a typed\n\t// error. Match only the stable server error header and keep the complete\n\t// original message for diagnostics. A response can contain more than one\n\t// Xugu error; vendorCode intentionally records the first/top-level code.\n\txuguServerErrorHeader = regexp.MustCompile(`(?im)^[\\t ]*(?:error:[\\t ]*)?\\[[\\t ]*E([0-9]{1,9})(?:[\\t ]+L([0-9]+))?(?:[\\t ]+C([0-9]+))?[\\t ]*\\]`)\n\txuguQueryTimeout      = regexp.MustCompile(`(?i)^query timed out after [1-9][0-9]*s$`)\n)\n\ntype rpcError struct {\n\tCode    int           `json:\"code\"`\n\tMessage string        `json:\"message\"`\n\tData    *rpcErrorData `json:\"data,omitempty\"`\n}\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/xugu/protocol_error.go#L1-L35","documentation":"errAgentSessionLimit is a sentinel error thrown when the agent registry has reached maxAgentSessions and cannot register another session. Callers wrap it with the current limit using %w, so errors.Is can detect it. classifyRPCError maps it into a structured error response with retryable=false.","triggerScenarios":"Calling session-creating RPCs (main.go:855 and main.go:921 paths) when len(r.sessions) >= maxAgentSessions; one at initial connect, another during control-session setup after which a stale server is disconnected and the limit is still hit.","commonSituations":"Long-lived agent sessions leaking (never disconnected), stress/load tests opening many sessions concurrently, or a low maxAgentSessions configuration in production.","solutions":["Disconnect idle sessions to free slots (server.disconnect / release the session)","Increase maxAgentSessions configuration if the workload legitimately needs more","Check for session leaks: ensure every created session is released on client exit","Retry later with backoff — the limit may free up as sessions close"],"exampleFix":"// before\nconn, err := r.connect(...) // err: \"agent session limit reached: 64\"\n// after\nif errors.Is(err, errAgentSessionLimit) {\n    r.releaseStaleSessions()\n    conn, err = r.connect(...) // retry\n}","handlingStrategy":"retry","validationCode":"// check capacity before creating sessions\nif r.sessionCount() >= maxAgentSessions {\n    return fmt.Errorf(\"at capacity; release a session first\")\n}","typeGuard":null,"tryCatchPattern":"sess, err := r.connect(cfg)\nvar capErr error\nif errors.As(err, &capErr) && errors.Is(err, errAgentSessionLimit) {\n    // wait/backoff then retry\n    time.Sleep(backoff)\n    sess, err = r.connect(cfg)\n}","preventionTips":["Release sessions deterministically via defer/disconnect on client exit","Monitor active session counts and alert near maxAgentSessions","Pool or reuse sessions instead of opening one per request"],"tags":["xugu","session-limit","capacity","retry"],"backgroundTag":"session-limit-reached","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}