jstedfast/MailKit · error · ObjectDisposedException
MD4
Error message
MD4
What it means
ComputeHash(byte[]) throws ObjectDisposedException named "MD4" when the hasher has already been disposed. MD4 implements IDisposable like other HashAlgorithms; after Dispose(), its internal state is cleared and further hashing is invalid. This guards against silently producing wrong hashes from a reset/cleared instance.
Solutions
- Create a new MD4 instance for each hash operation instead of reusing a disposed one.
- Remove the Dispose call (or the using block) on the path that still needs the hasher, and manage lifetime in one owner.
- If reuse is needed, wrap access so Dispose happens only after all hashing completes (e.g. lazy dispose at service shutdown).
- Optionally catch ObjectDisposedException at the boundary to detect lifetime bugs, but prefer fixing ownership.
Example fix
// before
using (var md4 = new MD4()) { }
md4.ComputeHash(data); // disposed
// after
using (var md4 = new MD4()) {
var hash = md4.ComputeHash(data);
} Defensive patterns
Strategy: validation
Validate before calling
if (md4 == null) throw new InvalidOperationException("MD4 not created");
// avoid the situation: do not keep using an instance after 'using' or Dispose(); create a fresh one per operation. Type guard
static bool IsUsable(MD4 md4) => md4 != null; // MD4 does not expose a disposed flag; enforce single-owner lifetime instead of probing
Try / catch
try { hash = md4.ComputeHash(data); }
catch (ObjectDisposedException) { md4 = new MD4(); hash = md4.ComputeHash(data); } // recovery: recreate; prefer fixing lifetime ownership Prevention
- Create one MD4 per hash operation; they are cheap
- Never store IDisposable hashers in static fields shared across requests
- Keep hashing inside the same using scope that created the instance
When it happens
Trigger: Calling ComputeHash(buffer) (or the offset/count overload, which routes here after its own checks) on an MD4 instance after a using block ended or Dispose() was called explicitly; caching an MD4 instance in a static field while also using it in a using statement.
Common situations: Long-lived NTLM helper class that holds an MD4 across requests while some code path disposes it; reusing a hasher created inside a using scope; double-dispose patterns where a wrapper disposes the hasher the caller still uses.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/f39141c68c810b19.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Security/Ntlm/MD4.cs:299
state [0] += a;
state [1] += b;
state [2] += c;
state [3] += d;
}
public byte[] ComputeHash (byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException (nameof (buffer));
if (offset < 0 || offset > buffer.Length)
throw new ArgumentOutOfRangeException (nameof (offset));
if (count < 0 || offset > buffer.Length - count)
throw new ArgumentOutOfRangeException (nameof (count));
if (disposed)
throw new ObjectDisposedException (nameof (MD4));
HashCore (buffer, offset, count);
hashValue = HashFinal ();
Initialize ();
return hashValue;
}
public byte[] ComputeHash (byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException (nameof (buffer));
return ComputeHash (buffer, 0, buffer.Length);
}
public byte[] ComputeHash (Stream inputStream)
{View on GitHub (pinned to 9d3859a785)