jstedfast/MailKit · error · ArgumentNullException
userName
Error message
userName
What it means
The NtlmAuthenticateMessage constructor throws ArgumentNullException when userName is null. The username is embedded in the Type3 AUTHENTICATE message, so it must be provided (an empty string is acceptable, null is not).
Solutions
- Pass a non-null userName (use string.Empty for anonymous/blank usernames).
- Validate credentials are populated before starting the NTLM handshake.
- Fix the config/env source so the username is loaded (e.g. check for missing settings).
Example fix
// before var auth = new NtlmAuthenticateMessage(negotiate, challenge, null, pass, domain, ws); // after var auth = new NtlmAuthenticateMessage(negotiate, challenge, userName ?? string.Empty, pass, domain, ws);
Defensive patterns
Strategy: validation
Validate before calling
if (userName == null) throw new InvalidOperationException("NTLM username is not configured.");
var auth = new NtlmAuthenticateMessage(negotiate, challenge, userName, password, domain, workstation); Type guard
static bool HasUserName(string userName) => !string.IsNullOrEmpty(userName);
Try / catch
try {
auth = new NtlmAuthenticateMessage(negotiate, challenge, userName, password, domain, workstation);
} catch (ArgumentNullException ex) when (ex.ParamName == "userName") {
// prompt for or reload credentials
userName = LoadConfiguredUserName() ?? string.Empty;
} Prevention
- Load and validate credentials at startup, before any network work.
- Use string.Empty (not null) for intentionally blank usernames.
- Surface missing-credential config errors with clear messages.
When it happens
Trigger: Calling new NtlmAuthenticateMessage(negotiate, challenge, null, password, domain, workstation), usually from unset credential variables or config fields.
Common situations: Credentials read from configuration/environment that were never populated; anonymous-auth code paths passing null instead of string.Empty.
Related errors
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/2912f1df6c0bfd62.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs:51
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.
Domain = challenge.TargetName ?? string.Empty;
} else if (challenge.TargetInfo != null) {
// The server is not domain-joined, so the TargetName will be the machine name of the server.
Domain = challenge.TargetInfo.DomainName ?? string.Empty;
} else {
Domain = string.Empty;View on GitHub (pinned to 9d3859a785)