{"record":{"id":"52ef7278b3ed2594","repo":"t8y2/dbx","slug":"agent-session-already-exists-s-52ef72","errorCode":null,"errorMessage":"Agent session already exists: %s","messagePattern":"Agent session already exists: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/etcd2-go/main.go","lineNumber":230,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, false, err\n\t\t}\n\t\tsession.mu.Lock()\n\t\tdefer session.mu.Unlock()\n\t\tresult, err := session.state.handle(method, params)\n\t\treturn result, false, err\n\t}\n}\n\nfunc requiredSessionID(params map[string]json.RawMessage) string {\n\treturn strings.TrimSpace(stringParam(params, \"agentSessionId\"))\n}\n\nfunc (r *runtimeServer) openSession(id string, params map[string]json.RawMessage) (any, bool, error) {\n\tr.mu.Lock()\n\tif _, exists := r.sessions[id]; exists {\n\t\tr.mu.Unlock()\n\t\treturn nil, false, fmt.Errorf(\"Agent session already exists: %s\", id)\n\t}\n\tif len(r.sessions) >= maxAgentSessions {\n\t\tr.mu.Unlock()\n\t\treturn nil, false, fmt.Errorf(\"Agent session limit reached: %d\", maxAgentSessions)\n\t}\n\tsession := &agentSession{state: newEtcd2Session()}\n\tr.sessions[id] = session\n\tr.mu.Unlock()\n\n\tif _, err := session.state.connect(params); err != nil {\n\t\tr.mu.Lock()\n\t\tdelete(r.sessions, id)\n\t\tr.mu.Unlock()\n\t\tsession.state.close()\n\t\treturn nil, false, err\n\t}\n\treturn map[string]bool{\"ok\": true}, false, nil\n}","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd2-go/main.go#L212-L248","documentation":"openSession refuses to create a runtime agent session whose id already exists in the runtimeServer's session map. Session ids are caller-chosen, so duplicates collide. The check happens under the mutex before any connection work, so no partial session is left behind.","triggerScenarios":"Calling openSession (or the session/open RPC that routes to it) with an id that was already opened and not closed; retrying an open after a timeout without changing the id.","commonSituations":"Client reconnect logic reusing a fixed session id, test harnesses opening the same id twice, a crashed client whose session still lives in the server process.","solutions":["Close the existing session first (closeSession) or generate a fresh unique id.","Treat the duplicate-open error as idempotent 'already open' and reuse the session if that is the intent.","Prefix ids with a UUID/pid per client instance to avoid cross-process collisions."],"exampleFix":"// before\nopenSession(\"agent-1\", params)\nopenSession(\"agent-1\", params) // throws\n// after\nopenSession(fmt.Sprintf(\"agent-%s\", uuid.NewString()), params)","handlingStrategy":"try-catch","validationCode":"// track ids client-side before opening\nif openedSessions[id] { return nil } // treat as already open","typeGuard":null,"tryCatchPattern":"session, err := openSession(id, params)\nif err != nil && strings.Contains(err.Error(), \"already exists\") {\n    session = reuseSession(id) // idempotent open\n}","preventionTips":["Generate unique ids (UUID) per client instance","Always pair openSession with closeSession on shutdown","Treat 'already exists' as idempotent success where safe"],"tags":["session","duplicate","etcd-agent"],"backgroundTag":"duplicate-resource","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"}