{"record":{"id":"e49637401bdd3ed4","repo":"github/copilot-sdk","slug":"session-session-sessionid-is-already-tracked-b","errorCode":null,"errorMessage":"Session '{session.SessionId}' is already tracked by this client.","messagePattern":"Session '(.+?)' is already tracked by this client\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Client.cs","lineNumber":2802,"sourceCode":"        options.TypeInfoResolverChain.Add(SessionEventsJsonContext.Default);\n        options.TypeInfoResolverChain.Add(GitHub.Copilot.Rpc.RpcJsonContext.Default);\n\n        options.MakeReadOnly();\n\n        return options;\n    }\n\n    internal CopilotSession? GetSession(string sessionId)\n    {\n        _sessions.TryGetValue(sessionId, out var session);\n        return session;\n    }\n\n    private void RegisterSession(CopilotSession session)\n    {\n        if (!_sessions.TryAdd(session.SessionId, session))\n        {\n            throw new InvalidOperationException($\"Session '{session.SessionId}' is already tracked by this client.\");\n        }\n    }\n\n    /// <summary>\n    /// Disposes the <see cref=\"CopilotClient\"/> synchronously.\n    /// </summary>\n    /// <remarks>\n    /// Prefer using <see cref=\"DisposeAsync\"/> for better performance in async contexts.\n    /// </remarks>\n    public void Dispose()\n    {\n        DisposeAsync().AsTask().GetAwaiter().GetResult();\n    }\n\n    /// <summary>\n    /// Disposes the <see cref=\"CopilotClient\"/> asynchronously.\n    /// </summary>\n    /// <returns>A <see cref=\"ValueTask\"/> representing the asynchronous dispose operation.</returns>","sourceCodeStart":2784,"sourceCodeEnd":2820,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/Client.cs#L2784-L2820","documentation":"RegisterSession adds a CopilotSession to the client's concurrent session map and throws InvalidOperationException if a session with the same SessionId is already tracked (ConcurrentDictionary.TryAdd returned false). It protects the invariant that each session id maps to exactly one session object.","triggerScenarios":"Calling an internal/registration path (directly or via resume flows) that registers a session whose SessionId already exists in the client's _sessions dictionary.","commonSituations":"Calling session-creation or resume APIs twice for the same session id; a race where two threads create sessions that the server assigned the same id; re-registering a session after a partial failure rolled back inconsistently.","solutions":["Check GetSession(id) for an existing session before creating/resuming one with the same id.","Reuse the tracked session instead of re-registering it.","Serialize session-creation calls (or await the first one) to avoid duplicate-id races.","If the id is server-assigned, log/report the duplicate — it indicates a server-side id collision."],"exampleFix":"// before\nvar s1 = await client.CreateSessionAsync();\nvar s2 = await client.ResumeSessionAsync(s1.SessionId); // already tracked\n\n// after\nvar session = client.GetSession(s1.SessionId) ?? await client.ResumeSessionAsync(s1.SessionId);","handlingStrategy":"validation","validationCode":"if (client.GetSession(sessionId) is not null)\n    return; // already tracked; reuse instead of registering again","typeGuard":"bool AlreadyTracked(CopilotClient c, string id) => c.GetSession(id) is not null;","tryCatchPattern":"try { RegisterSession(session); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already tracked\"))\n{ /* reuse existing session */ }","preventionTips":["Look up existing sessions before create/resume","Serialize session-creation calls to avoid duplicate-id races","Keep a single source of truth for active session ids"],"tags":["session","duplicate","state","dotnet"],"backgroundTag":"invalid-state-transition","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}