jstedfast/MailKit · error · ObjectDisposedException

HashAlgorithm

Error message

HashAlgorithm

What it means

HMACMD5.ComputeHash(buffer, offset, count) throws an ArgumentOutOfRange with the name 'HashAlgorithm' when the instance has already been disposed. MailKit's NTLM HMACMD5 mimics System.Security.Cryptography.HashAlgorithm, which signals a used-up object via ObjectDisposedException('HashAlgorithm'). Once Dispose() runs, the internal MD5 state is gone and hashing can no longer proceed.

Solutions

  1. Create a new HMACMD5 instance for each ComputeHash call instead of reusing a disposed one
  2. Move ComputeHash calls inside the using/undisposed scope
  3. Verify no double-dispose via IDisposable cascades (e.g., SaslMechanism disposing the HMAC early)

Example fix

// before
using (var hmac = new HMACMD5 (key)) { }
byte[] hash = hmac.ComputeHash (data); // ObjectDisposedException
// after
using (var hmac = new HMACMD5 (key)) {
    byte[] hash = hmac.ComputeHash (data);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (hmac == null) throw new InvalidOperationException ("HMACMD5 not created");
// MailKit's HMACMD5 exposes no public IsDisposed; track it yourself:
bool disposed = false;
if (disposed) throw new InvalidOperationException ("HMAC instance already disposed");

Type guard

static bool IsUsable (HMACMD5? hmac) => hmac != null && !ReferenceEquals (hmac, null);

Try / catch

try {
    byte[] hash = hmac.ComputeHash (data);
} catch (ObjectDisposedException) {
    hmac = new HMACMD5 (key);
    byte[] hash = hmac.ComputeHash (data);
}

Prevention

When it happens

Trigger: Calling ComputeHash after HMACMD5.Dispose() was invoked (explicitly or via using block); reusing a single instance across two authentication attempts where the first attempt disposed it.

Common situations: Reusing one HMACMD5 instance for multiple NTLM auth rounds in a connection pool; wrapping the hash in 'using' then calling ComputeHash afterwards; disposal triggered by an outer authenticate() finally block.

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/9bcc391c94e7ba0e. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Security/Ntlm/HMACMD5.cs:112

		public void Clear ()
		{
			Dispose (false);
		}

		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 ("HashAlgorithm");

			HashCore (buffer, offset, count);
			hashValue = HashFinal ();

			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)
		{
			// don't read stream unless object is ready to use

View on GitHub (pinned to 9d3859a785)