{"record":{"id":"d9f7ceda37588c88","repo":"t8y2/dbx","slug":"agent-session-already-exists-s-d9f7ce","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/etcd-go/main.go","lineNumber":259,"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: newEtcdSession()}\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":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd-go/main.go#L241-L277","documentation":"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.","triggerScenarios":"Calling the runtime 'open' method (routed to runtimeServer.openSession) with an id already present in r.sessions while the previous session was never closed.","commonSituations":"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.","solutions":["Close the existing session first (call the close/shutdown method for that id) and retry openSession","Use a fresh unique session id (UUID) for each openSession call","Track session ids client-side and treat 'already exists' as 'session is live' — reuse it instead of reopening"],"exampleFix":"// before\nclient.call(\"open\", map[string]any{\"id\": \"agent-1\"})\nclient.call(\"open\", map[string]any{\"id\": \"agent-1\"}) // panics with duplicate\n\n// after\nif _, err := client.call(\"open\", map[string]any{\"id\": id}); err != nil {\n    client.call(\"close\", map[string]any{\"id\": id})\n    client.call(\"open\", map[string]any{\"id\": id})\n}","handlingStrategy":"try-catch","validationCode":"// Go: check the id is fresh before opening (best-effort; server is authoritative)\nif _, err := runtime.Call(\"get\", map[string]any{\"id\": id}); err == nil {\n    return fmt.Errorf(\"session %s appears to already exist\", id)\n}","typeGuard":null,"tryCatchPattern":"_, err := runtime.Call(\"open\", map[string]any{\"id\": id})\nif err != nil && strings.Contains(err.Error(), \"already exists\") {\n    runtime.Call(\"close\", map[string]any{\"id\": id})\n    _, err = runtime.Call(\"open\", map[string]any{\"id\": id})\n}","preventionTips":["Generate a unique session id (UUID) per client instance","Always pair open with close/shutdown, including on error paths","Treat 'already exists' as a signal to reuse, not blindly retry open"],"tags":["go","etcd","session-management","duplicate-resource"],"backgroundTag":"duplicate-session-id","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}