jstedfast/MailKit · error · ArgumentNullException

negotiate

Error message

negotiate

What it means

The NtlmAuthenticateMessage constructor throws ArgumentNullException when the negotiate parameter is null. The NTLM AUTHENTICATE message requires the preceding NEGOTIATE message to build the Type3 payload, so it is a mandatory argument.

Solutions

  1. Create the NtlmNegotiateMessage before constructing the authenticate message.
  2. Check the negotiate value for null before calling the constructor.
  3. If negotiate comes from a parse/decode call, handle its failure path instead of passing null through.

Example fix

// before
var auth = new NtlmAuthenticateMessage(negotiate, challenge, user, pass, domain, ws); // negotiate is null
// after
if (negotiate == null) negotiate = new NtlmNegotiateMessage();
var auth = new NtlmAuthenticateMessage(negotiate, challenge, user, pass, domain, ws);
Defensive patterns

Strategy: validation

Validate before calling

if (negotiate == null) throw new InvalidOperationException("NTLM negotiate message must be created before the authenticate message.");
var auth = new NtlmAuthenticateMessage(negotiate, challenge, userName, password, domain, workstation);

Type guard

static bool CanBuildAuthMessage(NtlmNegotiateMessage n, NtlmChallengeMessage c) => n != null && c != null;

Try / catch

try {
	auth = new NtlmAuthenticateMessage(negotiate, challenge, userName, password, domain, workstation);
} catch (ArgumentNullException ex) when (ex.ParamName == "negotiate") {
	// recreate the Type1 message and retry the handshake
	negotiate = new NtlmNegotiateMessage();
	auth = new NtlmAuthenticateMessage(negotiate, challenge, userName, password, domain, workstation);
}

Prevention

When it happens

Trigger: Calling new NtlmAuthenticateMessage(null, challenge, ...) — e.g. the negotiate message was never created or a method returned null on a parse failure.

Common situations: Siloed NTLM handshake code where the Type1 message creation is skipped or its parse failed silently; refactors that reorder the handshake steps.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/393437f0a65818ec. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs:45

// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b38c36ed-2804-4868-a9ff-8dd3182128e4

using System;
using System.Text;
using System.Diagnostics.CodeAnalysis;

namespace MailKit.Security.Ntlm {
	class NtlmAuthenticateMessage : NtlmMessageBase
	{
		static readonly byte[] Z16 = new byte[16];

		readonly NtlmNegotiateMessage? negotiate;
		readonly NtlmChallengeMessage? challenge;
		byte[] clientChallenge;

		public NtlmAuthenticateMessage (NtlmNegotiateMessage negotiate, NtlmChallengeMessage challenge, string userName, string password, string domain, string workstation) : base (3)
		{
			if (negotiate == null)
				throw new ArgumentNullException (nameof (negotiate));

			if (challenge == null)
				throw new ArgumentNullException (nameof (challenge));

			if (userName == null)
				throw new ArgumentNullException (nameof (userName));

			if (password == null)
				throw new ArgumentNullException (nameof (password));

			clientChallenge = NtlmUtils.NONCE (8);
			this.negotiate = negotiate;
			this.challenge = challenge;

			if (!string.IsNullOrEmpty (domain)) {
				Domain = domain;
			} else if ((challenge.Flags & NtlmFlags.TargetTypeDomain) != 0) {
				// The server is domain-joined, so the TargetName will be the domain.

View on GitHub (pinned to 9d3859a785)