{"record":{"id":"aa5b2e59de11800a","repo":"jstedfast/MailKit","slug":"incompletechallenge","errorCode":"IncompleteChallenge","errorMessage":"Server response contained incomplete authentication data.","messagePattern":"Server response contained incomplete authentication data\\.","errorType":"error_code","errorClass":"SaslException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/SaslMechanismDigestMd5.cs","lineNumber":166,"sourceCode":"\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.ChallengeTooLong, \"Server challenge too long.\");\n\n\t\t\t\tchallenge = DigestChallenge.Parse (Encoding.UTF8.GetString (token, startIndex, length));\n\t\t\t\tencoding = challenge.Charset != null ? Encoding.UTF8 : TextEncodings.Latin1;\n\t\t\t\tcnonce ??= GenerateEntropy (15);\n\n\t\t\t\tresponse = new DigestResponse (challenge, encoding, Uri.Scheme, Uri.DnsSafeHost, AuthorizationId, Credentials.UserName, Credentials.Password, cnonce);\n\t\t\t\tstate = LoginState.Final;\n\n\t\t\t\treturn response.Encode (encoding);\n\t\t\tcase LoginState.Final:\n\t\t\t\tif (token == null || token.Length == 0)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.MissingChallenge, \"Server response did not contain any authentication data.\");\n\n\t\t\t\tvar text = encoding!.GetString (token, startIndex, length);\n\t\t\t\tstring? key, value;\n\n\t\t\t\tif (!DigestChallenge.TryParseKeyValuePair (text, out key, out value))\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.IncompleteChallenge, \"Server response contained incomplete authentication data.\");\n\n\t\t\t\tif (!key.Equals (\"rspauth\", StringComparison.OrdinalIgnoreCase))\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.InvalidChallenge, \"Server response contained invalid data.\");\n\n\t\t\t\tvar expected = response!.ComputeHash (encoding, Credentials.Password, false);\n\t\t\t\tif (value != expected)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.IncorrectHash, \"Server response did not contain the expected hash.\");\n\n\t\t\t\tIsAuthenticated = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Reset the state of the SASL mechanism.\n\t\t/// </summary>","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/SaslMechanismDigestMd5.cs#L148-L184","documentation":"In the DIGEST-MD5 final step, the server's response must be a key/value pair whose key is 'rspauth'; otherwise the response is incomplete. SaslMechanismDigestMd5.Challenge throws SaslException with code SaslErrorCode.IncompleteChallenge when TryParseKeyValuePair fails to parse the server data.","triggerScenarios":"Server's final DIGEST-MD5 message is not a parseable 'key=value' pair — e.g. empty garbage, a base64 blob, an error string, or a message missing the '=' separator.","commonSituations":"Non-conformant servers appending extra text after rspauth, servers sending error text where the final response belongs, protocol confusion where the server replies with a different SASL mechanism's message.","solutions":["Verify the server's final response format against RFC 2831; fix or report the server implementation.","Capture a network trace of the raw final response to identify the malformed content and its source (proxy/middleware).","Catch SaslException with ErrorCode == SaslErrorCode.IncompleteChallenge and fall back to a simpler mechanism (PLAIN/CRAM-MD5 over TLS)."],"exampleFix":"// before\nclient.Authenticate(uri, new SaslMechanismDigestMd5(uri, user, pass)); // server sends malformed final message\n// after\ntry {\n    client.Authenticate(uri, new SaslMechanismDigestMd5(uri, user, pass));\n} catch (SaslException ex) when (ex.ErrorCode == SaslErrorCode.IncompleteChallenge) {\n    client.Authenticate(uri, new SaslMechanismCramMd5(user, pass));\n}","handlingStrategy":"try-catch","validationCode":"// validate server compliance out-of-band; at runtime guard the exchange:\ntry { /* authenticate */ } catch (SaslException ex) when (ex.ErrorCode == SaslErrorCode.IncompleteChallenge) { /* fallback */ }","typeGuard":null,"tryCatchPattern":"try {\n    client.Authenticate(uri, new SaslMechanismDigestMd5(uri, user, pass));\n} catch (SaslException ex) when (ex.ErrorCode == SaslErrorCode.IncompleteChallenge) {\n    // server's final response was not a parseable rspauth pair\n    client.Authenticate(uri, new SaslMechanismCramMd5(user, pass));\n}","preventionTips":["Capture a network trace of the final DIGEST-MD5 message when parsing fails","Switch to SCRAM mechanisms to avoid DIGEST-MD5 parsing quirks","Always filter SaslException by ErrorCode before choosing a fallback"],"tags":["sasl","digest-md5","protocol-parsing","server-compatibility"],"backgroundTag":"invalid-argument-format","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"}