{"record":{"id":"9809cf8783fcc68e","repo":"jstedfast/MailKit","slug":"objectdisposedexception","errorCode":null,"errorMessage":"ObjectDisposedException","messagePattern":"ObjectDisposedException","errorType":"exception","errorClass":"ObjectDisposedException","httpStatus":null,"severity":"error","filePath":"MailKit/DuplexStream.cs","lineNumber":170,"sourceCode":"\t\t\tget { throw new NotSupportedException (); }\n\t\t}\n\n\t\tstatic void ValidateArguments (byte[] buffer, int offset, int count)\n\t\t{\n\t\t\tif (buffer == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (buffer));\n\n\t\t\tif (offset < 0 || offset > buffer.Length)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (offset));\n\n\t\t\tif (count < 0 || count > (buffer.Length - offset))\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (count));\n\t\t}\n\n\t\tvoid CheckDisposed ()\n\t\t{\n\t\t\tif (disposed)\n\t\t\t\tthrow new ObjectDisposedException (nameof (DuplexStream));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Reads a sequence of bytes from the stream and advances the position\n\t\t/// within the stream by the number of bytes read.\n\t\t/// </summary>\n\t\t/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many\n\t\t/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>\n\t\t/// <param name=\"buffer\">The buffer.</param>\n\t\t/// <param name=\"offset\">The buffer offset.</param>\n\t\t/// <param name=\"count\">The number of bytes to read.</param>\n\t\t/// <exception cref=\"System.ArgumentNullException\">\n\t\t/// <paramref name=\"buffer\"/> is <see langword=\"null\" />.\n\t\t/// </exception>\n\t\t/// <exception cref=\"System.ArgumentOutOfRangeException\">\n\t\t/// <para><paramref name=\"offset\"/> is less than zero or greater than the length of <paramref name=\"buffer\"/>.</para>\n\t\t/// <para>-or-</para>\n\t\t/// <para>The <paramref name=\"buffer\"/> is not large enough to contain <paramref name=\"count\"/> bytes starting","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/DuplexStream.cs#L152-L188","documentation":"CheckDisposed throws ObjectDisposedException(nameof(DuplexStream)) when Read, ReadAsync, Write, WriteAsync, Flush or FlushAsync is called after Dispose has run. It protects against using an underlying duplex pipe whose resources were already released.","triggerScenarios":"Calling any read/write/flush method on a DuplexStream after Dispose() (or a 'using' block scope that has exited), including async continuations that run after the using block ends.","commonSituations":"Firing async read/write tasks and disposing the stream before they complete (e.g. cancellation without awaiting); storing the stream in a field and reusing it after a using scope; double-dispose followed by retry logic.","solutions":["Ensure all I/O on the stream completes (await tasks) before Dispose; check for unawaited async operations.","Keep the stream alive for the duration of its use; widen the using scope or switch to explicit Dispose at the correct point.","If lifecycle is racy, check for disposal via your own flag or catch ObjectDisposedException around late operations."],"exampleFix":"// before\nusing (var duplex = new DuplexStream (a, b)) {\n    var task = duplex.ReadAsync (buffer, 0, buffer.Length);\n}\nvar n = await task; // throws\n// after\nusing (var duplex = new DuplexStream (a, b)) {\n    var n = await duplex.ReadAsync (buffer, 0, buffer.Length);\n}","handlingStrategy":"try-catch","validationCode":"if (!ownStream) { /* track lifetime with your own disposed flag before use */ }\nprivate bool disposed;\nif (disposed) return; // caller-side guard","typeGuard":null,"tryCatchPattern":"try { await stream.ReadAsync (buffer, 0, buffer.Length); }\ncatch (ObjectDisposedException) { /* stream already disposed: re-acquire or abort */ }","preventionTips":["Await all async I/O before leaving the using scope that owns the stream.","Do not store streams in long-lived fields if they are created in short-lived using blocks.","Serialize access and disposal: one owner decides when the stream dies."],"tags":["io","stream","disposed","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}