Exchange ServerDeep dive

TLS, Schannel and certificate errors on Exchange Server: a quick reference

Decode TLS problems on Exchange Server: what Schannel 36887, TLS alert 48, 0x80090331, RevocationCheckFailure and 45 more mean, the usual cause and the first thing to check.

TLS problems on Exchange Server rarely explain themselves in Exchange's own words. You get a Schannel event number in the System log, a TLS alert code, a hex error in a wizard or script, or a certificate status in the Exchange admin center. This quick reference decodes them: the meaning from Microsoft's documentation, the usual cause on an Exchange server and the first thing to check. Errors that already have a detailed guide on this site are linked at the end.

Codes in this quick reference

  • Schannel 36887: A fatal alert was received from the remote endpoint (TLS alert code in the text)System log (Schannel)
  • Schannel 36888: A fatal alert was generated and sent to the remote endpointSystem log (Schannel)
  • Schannel 36874: none of the cipher suites supported by the client application are supported by the serverSystem log (Schannel)
  • Schannel 36873: No supported cipher suites were found when initiating a connectionSystem log (Schannel)
  • Schannel 36870: A fatal error occurred when attempting to access the credential private keySystem log (Schannel)
  • Schannel 36871: A fatal error occurred while creating a TLS credentialSystem log (Schannel)
  • Schannel 36869: the credential's certificate does not have a private key information property attachedSystem log (Schannel)
  • Schannel 36872 / 36886: No suitable default server credential exists on this systemSystem log (Schannel)

+ 41 more codes in the tables below.

How this guide is organized: How to read these errors → Schannel events in the System log → TLS alert codes in events 36887 and 36888 → Windows security and certificate error codes → Exchange certificate status errors → Related errors with their own guides → How to verify a fixFlow diagram of the article's sections in reading order: 1. How to read these errors. 2. Schannel events in the System log. 3. TLS alert codes in events 36887 and 36888. 4. Windows security and certificate error codes. 5. Exchange certificate status errors. 6. Related errors with their own guides. 7. How to verify a fix. Toolbox: 0x8009030D, 0x80090331, 0x80090325, Get-ExchangeCertificate, certutil -verify.1How to read theseerrors2Schannel events inthe System log3TLS alert codes inevents 36887 and 3…4Windows securityand certificate error…5Exchange certificatestatus errors6Related errors withtheir own guides7How to verify a fixTOOLBOX0x8009030D0x800903310x80090325Get-ExchangeCertificatecertutil -verifyHow this guide is organized: How to read these errors → Schannel events in the System log → TLS alert codes in events 36887 and 36888 → Windows security and certificate error codes → Exchange certificate status errors → Related errors with their own guides → How to verify a fixFlow diagram of the article's sections in reading order: 1. How to read these errors. 2. Schannel events in the System log. 3. TLS alert codes in events 36887 and 36888. 4. Windows security and certificate error codes. 5. Exchange certificate status errors. 6. Related errors with their own guides. 7. How to verify a fix. Toolbox: 0x8009030D, 0x80090331, 0x80090325, Get-ExchangeCertificate, certutil -verify.1How to read these errors2Schannel events in the System log3TLS alert codes in events 36887 and 368884Windows security and certificate error codes5Exchange certificate status errors6Related errors with their own guides7How to verify a fixTOOLBOX0x8009030D0x800903310x80090325Get-ExchangeCertificatecertutil -verify
At a glance: how this guide is organized · 7 sections · 5 key settings and tools

How to read these errors#

Reading a TLS error by where it appearsWhere did the error show up? if Schannel event: Which event ID is it? if 36887: The other side rejected this server (Decode its TLS alert code; match the time in SMTP, IIS or load balancer logs); if 36888: This server rejected the other side (Decode the TLS alert code; scanners and health probes trigger these too); if Another ID: Look it up under Schannel events (Raise EventLogging from 1 to 3 for more detail, then set it back); if Hex code: Look up the security or certificate code (SEC_E, CRYPT_E, CERT_E or NTE codes from events, certutil or wizards); if Certificate status: Check the Exchange certificate status (Read Status and HasPrivateKey for the certificates Exchange uses)Where did the error show up?Which event ID is it?NOTEThe other siderejected thisserverDecode its TLS alertcode; match the timein SMTP, IIS or loadbalancer logs36887NOTEThis serverrejected theother sideDecode the TLS alertcode; scanners andhealth probes triggerthese too36888NOTELook it up underSchannel eventsRaise EventLoggingfrom 1 to 3 for moredetail, then set itbackAnother IDSchannel eventNOTELook up thesecurity orcertificate codeSEC_E, CRYPT_E,CERT_E or NTEcodes from events,certutil or wizardsHex codeNOTECheck theExchangecertificate statusRead Status andHasPrivateKey forthe certificatesExchange usesCertificate statusReading a TLS error by where it appearsWhere did the error show up? if Schannel event: Which event ID is it? if 36887: The other side rejected this server (Decode its TLS alert code; match the time in SMTP, IIS or load balancer logs); if 36888: This server rejected the other side (Decode the TLS alert code; scanners and health probes trigger these too); if Another ID: Look it up under Schannel events (Raise EventLogging from 1 to 3 for more detail, then set it back); if Hex code: Look up the security or certificate code (SEC_E, CRYPT_E, CERT_E or NTE codes from events, certutil or wizards); if Certificate status: Check the Exchange certificate status (Read Status and HasPrivateKey for the certificates Exchange uses)Where did the error show up?Schannel eventWhich event ID is it?36887NOTEThe other side rejected this serverDecode its TLS alert code; match the time inSMTP, IIS or load balancer logs36888NOTEThis server rejected the other sideDecode the TLS alert code; scanners and healthprobes trigger these tooAnother IDNOTELook it up under Schannel eventsRaise EventLogging from 1 to 3 for more detail,then set it backHex codeNOTELook up the security or certificate codeSEC_E, CRYPT_E, CERT_E or NTE codes from events,certutil or wizardsCertificate statusNOTECheck the Exchange certificate statusRead Status and HasPrivateKey for the certificatesExchange uses
Figure 1 · Decision tree Reading a TLS error by where it appears. Start from where you saw the error. For Schannel events the direction matters: 36887 means you were rejected, 36888 means this server rejected the other side.
  • System log, source Schannel: Windows logs TLS handshake failures here, not in the Application log. Microsoft documents raising the EventLogging value under HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL from 1 to 3 for more detail; set it back when you're done.
  • Direction matters: 36887 means the other side sent a fatal alert (it rejected you); 36888 means this server generated one (it rejected the other side). Both carry a TLS alert code, decoded below. Current Windows versions say TLS where older documentation says SSL.
  • Find the other party yourself: these events don't say which client or process was involved, so match the time against the SMTP protocol logs, IIS logs or your load balancer. Scanners and health probes trigger them too.
  • Hex codes: SEC_E, CRYPT_E, CERT_E and NTE codes appear inside Schannel events, in certutil -verify output and in error text from the Hybrid Configuration Wizard, scripts and .NET applications.
PowerShell
# Which Schannel events, and how many, in the last 24 hours
Get-WinEvent -FilterHashtable @{ LogName = "System"; ProviderName = "Schannel"; StartTime = (Get-Date).AddDays(-1) } |
    Group-Object Id | Sort-Object Count -Descending | Format-Table Count, Name -AutoSize

# The certificates Exchange uses, with status and private key
Get-ExchangeCertificate | Format-Table Thumbprint, Services, Status, HasPrivateKey, NotAfter -AutoSize

Schannel events in the System log#

EventMeaningUsual causeFirst check
36887A fatal alert was received from the remote endpoint; the text gives the TLS alert codeThe partner, client or a device in between refused the handshakeThe alert code (next table); same time in SMTP or IIS logs
36888A fatal alert was generated and sent to the remote endpointThis server refused the handshake; alert 40 often comes with 36874The alert code; what the client offers
36874None of the cipher suites supported by the client application are supported by the server; the request failedOld clients, devices or scanners offering only protocols or ciphers you disabledHealth Checker TLS results (TLS hardening guide)
36873No supported cipher suites were found when this server started a connectionOver-tight protocol or cipher settings, or an app asking for disabled protocolsGet-TlsCipherSuite; Health Checker
36870A fatal error occurred when attempting to access the credential private key; the text gives a code such as 0x8009030DMicrosoft lists MachineKeys permissions, failed revocation or chain checks and expirycertutil -verifystore My <thumbprint>
36871A fatal error occurred while creating a TLS credentialA process asked for a protocol, cipher or certificate the server can't provide; admins often report it after TLS hardeningWhich service fails at that time; protocol settings
36869The credential's certificate does not have a private key information property attachedCertificate imported without its key, restored from a bad backup, or a failed enrollmentGet-ExchangeCertificate | fl Thumbprint,HasPrivateKey
36872 / 36886No suitable default server credential exists on this systemApps using the system default credential found none; apps that pick their own certificate, like IIS, aren't affectedExpected where no enterprise CA issues server certificates
36876The certificate received from the remote server has not validated correctly; the text gives the error codePartner certificate expired, untrusted or revokedDecode the code (Windows codes table)
36877The certificate received from the remote client application has not validated correctlyA connecting partner's certificate chains to a CA this server doesn't trustTrusted root and intermediate stores
36881The certificate received from the remote server has expiredThe smart host's or partner's certificate lapsedAsk the partner to renew it
36882The certificate received from the remote server was issued by an untrusted certification authorityPrivate CA, a root missing on this server, or an incomplete chainTheir certificate with certutil -verify -urlfetch
36883The certificate received from the remote server has been revokedThe CA revoked the partner's certificateThe partner must replace it
36884The certificate received from the remote server does not contain the expected nameThe connector targets a name or IP address that isn't on the partner's certificateGet-SendConnector | fl SmartHosts,TlsAuthLevel,TlsDomain

TLS alert codes in events 36887 and 36888#

The number in the event text is a TLS alert. Microsoft's table maps each alert (listed there as TLS1_ALERT_* and SSL3_ALERT_* constants) to the Schannel error Windows returns.

AlertMeaningUsual causeFirst check
10 unexpected_messageAn inappropriate message arrived (SEC_E_ILLEGAL_MESSAGE)A device in the path interfering with the sessionFirewall SMTP or TLS inspection
20 bad_record_macA record failed its integrity check (SEC_E_MESSAGE_ALTERED)Traffic altered or corrupted in transitDevices that inspect or rewrite traffic
40 handshake_failureNo acceptable set of security parameters (SEC_E_ILLEGAL_MESSAGE)No protocol version or cipher suite in commonEnabled protocols and ciphers on both sides
42 bad_certificateThe certificate was corrupt or its signature invalid (SEC_E_CERT_UNKNOWN)Damaged certificate or badly built chainThe certificate and chain you present
43 unsupported_certificateThe peer doesn't support this type of certificate (SEC_E_CERT_UNKNOWN)A key type or signature algorithm the peer can't useKey algorithm and size
44 certificate_revokedThe certificate was revoked by its issuer (CRYPT_E_REVOKED)A replaced certificate still bound somewhereIIS bindings, SMTP services, connectors
45 certificate_expiredThe certificate expired or isn't valid yet (SEC_E_CERT_EXPIRED)Expired certificate on a site or connector, or a wrong clockNotAfter; w32tm /query /status
46 certificate_unknownAnother certificate problem made it unacceptable (SEC_E_CERT_UNKNOWN)Often trust or name problems as seen by the side that sent itcertutil -verify -urlfetch on your certificate
48 unknown_caThe issuing CA couldn't be found or trusted (SEC_E_UNTRUSTED_ROOT)Missing intermediate on your server, a private CA or a self-signed certificateIntermediates installed; complete chain
49 access_deniedA valid certificate, but access control refused it (SEC_E_LOGON_DENIED)The peer's policy doesn't accept this senderThe partner's TLS policy
50 decode_errorA message couldn't be decoded (SEC_E_ILLEGAL_MESSAGE)Malformed traffic, an old TLS stack or a middleboxDevices in the path; client updates
51 decrypt_errorA handshake cryptographic operation failed (SEC_E_DECRYPT_FAILURE)Signature or key exchange problemsThe certificate's key; devices in the path
70 protocol_versionThe offered protocol version isn't supported (SEC_E_UNSUPPORTED_FUNCTION)One side only allows TLS versions the other has disabledHealth Checker; the client's TLS support
71 insufficient_securityThe peer needs stronger ciphers than offered (SEC_E_ALGORITHM_MISMATCH)Weak cipher order or strong suites disabledCipher suites on both sides
80 internal_errorAn internal error unrelated to the peer (SEC_E_INTERNAL_ERROR)A fault on the side that sent itThat side's own logs
90 user_canceledThe handshake was canceled (SEC_E_UNFINISHED_CONTEXT_DELETED)An application or probe closed the connectionUsually harmless

Windows security and certificate error codes#

CodeMessageUsual causeFirst check
0x80090331 SEC_E_ALGORITHM_MISMATCHThe client and server cannot communicate, because they do not possess a common algorithm.TLS 1.2 not available to .NET or the OS on one side, or ciphers disabledSystemDefaultTlsVersions and SchUseStrongCrypto (TLS guide)
0x80090325 SEC_E_UNTRUSTED_ROOTThe certificate chain was issued by an authority that is not trusted.Self-signed or private-CA certificate where a trusted one is expected, or a missing rootIssuer and chain of the certificate in use
0x80090328 SEC_E_CERT_EXPIREDThe received certificate has expired.Expired certificate on one sideNotAfter of the certificate presented
0x80090326 SEC_E_ILLEGAL_MESSAGEThe message received was unexpected or badly formatted.A failed handshake: alerts 10, 40, 50 and others map to itThe alert code in 36887 or 36888
0x80090327 SEC_E_CERT_UNKNOWNAn unknown error occurred while processing the certificate.Alerts 42, 43 or 46: the peer rejected the certificatecertutil -verify -urlfetch
0x8009030D SEC_E_UNKNOWN_CREDENTIALSThe credentials supplied to the package were not recognizedSchannel can't use the certificate, see event 36870certutil -verifystore My <thumbprint>
0x8009030E SEC_E_NO_CREDENTIALSNo credentials are available in the security packageNo usable certificate for the name or serviceCertificate services and names (Event 12014 guide)
0x80090302 SEC_E_UNSUPPORTED_FUNCTIONThe function requested is not supportedAlert 70: protocol version mismatchEnabled TLS versions on both sides
0x80090016 NTE_BAD_KEYSETKeyset does not existPrivate key deleted, unreadable or never importedReimport the PFX with its private key
0x80092010 CRYPT_E_REVOKEDThe certificate is revoked.Revoked by the CA, often after a rekeyBind the replacement everywhere
0x80092012 CRYPT_E_NO_REVOCATION_CHECKThe revocation function was unable to check revocation for the certificate.No reachable or valid revocation informationcertutil -verify -urlfetch
0x80092013 CRYPT_E_REVOCATION_OFFLINEThe revocation function was unable to check revocation because the revocation server was offline.The server can't reach the CRL or OCSP address: proxy or firewallnetsh winhttp show proxy
0x800B0109 CERT_E_UNTRUSTEDROOTA certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.Root CA missing from the Trusted Root storeRoot store; root certificate updates
0x800B010A CERT_E_CHAININGA certificate chain could not be built to a trusted root authority.Intermediate CA certificate missingInstall the CA's intermediates on every server
0x800B0101 CERT_E_EXPIREDA required certificate is not within its validity period (checked against the system clock)Expired or not-yet-valid certificate, or a wrong clockNotBefore and NotAfter; time sync
0x800B010F CERT_E_CN_NO_MATCHThe certificate's CN name does not match the passed value.Connecting by a name that isn't on the certificateCertificate names vs the URL (name mismatch guide)
0x8009310B CRYPT_E_ASN1_BADTAGASN1 bad tag value met.The file isn't a certificate in the expected format or encodingDownload the issued certificate again

Exchange certificate status errors#

MessageMeaningUsual causeFirst check
The certificate status could not be determined because the revocation check failed.The EAC can't confirm the certificate isn't revokedExchange uses WinHTTP for HTTP traffic, and WinHTTP ignores the browser's proxy settingsnetsh winhttp show proxy
Status: RevocationCheckFailureThe same condition in Get-ExchangeCertificateAs aboveConfigure the WinHTTP proxy with a bypass list
Command Prompt
netsh winhttp show proxy
netsh winhttp set proxy proxy-server="http=proxy.contoso.com:8080" bypass-list="*.contoso.com"

Watch out: Microsoft notes that if you set the WinHTTP proxy without the Exchange servers' names in the bypass list, the Exchange Management Shell and the EAC can't use Remote PowerShell.

How to verify a fix#

  1. Schannel: rerun the event count; the errors stop. If you also log informational events, event 36880 records each successful handshake with the protocol and cipher.
  2. Certificate: Get-ExchangeCertificate shows Valid, a private key and the right services, and certutil -verify -urlfetch reports no chain or revocation errors.
  3. Mail flow and clients: the SMTP protocol log shows STARTTLS followed by a completed TLS session, and Health Checker shows no TLS warnings.
PowerShell
$cert = Get-Item Cert:\LocalMachine\My\<thumbprint>
Export-Certificate -Cert $cert -FilePath "$env:TEMP\exchange.cer" | Out-Null
certutil -verify -urlfetch "$env:TEMP\exchange.cer"
Get-ExchangeCertificate -Thumbprint <thumbprint> | Format-List Status, HasPrivateKey, Services, NotAfter

Good: certutil ends with -verify command completed successfully, and the certificate status is Valid. Then set the Schannel EventLogging value back to 1.

References#

Written and checked against current Microsoft Learn documentation. Test changes with a pilot group before rolling them out to everyone, and if an admin center path has moved since, search for the setting name instead.

Spotted a mistake, or did this fix work differently for you? Email me or message me on LinkedIn — corrections are credited in the article.

Written by

Omer Eltayeb

Intune Subject Matter Expert in Cairo, Egypt, former Microsoft Cloud Solutions Architect, Microsoft Certified Trainer and Microsoft Innovative Educator Expert (2024–26) and Microsoft Elevate Educator Expert (2026–27). I share practical, step-by-step guides, study plans, scripts and toolkits for Microsoft Intune, Configuration Manager, Microsoft Entra ID, Microsoft Defender, Exchange and Microsoft 365 with the community.

Microsoft Certified Trainer (MCT) 2026Microsoft Innovative Educator Expert 2025–2026Microsoft Elevate Educator Expert 2026–2027ISC2 Certified Information Systems Security Professional (CISSP)Microsoft 365 Certified: Enterprise Administrator Expert (MS-102)