Phones and operating systems

Schannel errors 36887, 36874, 36871 and SEC_E codes on Windows

By · Last verified

Error messageA fatal alert was received from the remote endpoint. The TLS protocol defined fatal alert code is 40. (Schannel Event ID 36887)

Schannel errors are how Windows reports TLS failures in its built-in security provider. They appear as System log events (36887, 36888, 36874, 36871) and as SEC_E_* or CRYPT_E_* codes in curl, Git, PowerShell and .NET. Each code points to one cause: an alert from the other side, a missing protocol or cipher, or a certificate problem.

Is it the site or your device?

Server-side events point to your own server; client-side codes need an outside check of the server first. Use the SSL checker:

curl ssl.sh/example.com
  • The server fails the check: fix the server (certificate, chain, protocols).
  • The server passes: the Windows machine is the issue, usually disabled TLS versions, a missing root, a proxy that blocks revocation checks, or HTTPS interception.

For server-side events on IIS or RDP hosts, the client is usually old or misconfigured; the alert code tells you which side to change.

Causes

1. Event 36887 / 36888 with an alert code

36887 means the remote side sent a fatal alert; 36888 means Windows sent one. Read the alert code: 40 (handshake_failure) and 70 (protocol_version) point to protocol or cipher mismatch; 42, 46 and 48 point to certificate trust; 80 is an internal error on the other side.

2. Event 36874: no shared cipher suite

A client offered only cipher suites the server has disabled. Compare the server's cipher order with the client's capabilities; use the cipher suite lookup to decode names.

3. Event 36871 with internal error 10013

A program asked Schannel for a protocol or algorithm disabled by registry or Group Policy, typically TLS 1.0 for an outdated app. Update the app or enable TLS 1.2 for it rather than re-enabling TLS 1.0.

4. SEC_E_UNTRUSTED_ROOT (0x80090325)

The certificate chain ends at a root Windows does not trust: a private CA, a missing intermediate, or a corporate proxy root not deployed to this machine. With curl or Git it reads:

schannel: next InitializeSecurityContext failed: SEC_E_UNTRUSTED_ROOT (0x80090325)

5. CRYPT_E_NO_REVOCATION_CHECK (0x80092012) / CRYPT_E_REVOCATION_OFFLINE (0x80092013)

Windows could not reach the CA's CRL or OCSP service, usually because a proxy or firewall blocks it. Allow the CA's revocation URLs.

6. SEC_E_WRONG_PRINCIPAL (0x80090322) and CERT_E_EXPIRED (0x800B0101)

Hostname mismatch and expired certificate respectively; see NET::ERR_CERT_COMMON_NAME_INVALID and NET::ERR_CERT_DATE_INVALID.

What it looks like on each device

Client What you see
Event Viewer (System log, source Schannel) Event IDs 36887, 36888, 36874, 36871, 36870
curl / Git for Windows (schannel backend) SEC_E_UNTRUSTED_ROOT (0x80090325), CRYPT_E_NO_REVOCATION_CHECK (0x80092012)
PowerShell / .NET The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel
Edge IE mode DLG_FLAGS_SEC_CERT_CN_INVALID and related codes

How site owners fix it

Enabling TLS 1.2, installing the full chain and fixing trust on clients cover most Schannel errors.

1. Enable TLS 1.2 (and TLS 1.3 where supported) for server and client. On Windows Server, under HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server and ...\Client, set Enabled to 1 and DisabledByDefault to 0, then reboot. Windows Server 2022 and later support TLS 1.3.

2. Install the full chain on IIS. Import the PFX including intermediates, and check the Intermediate Certification Authorities store.

3. For Git on corporate networks, prefer fixing trust over disabling checks:

git config --global http.sslBackend schannel

With the schannel backend, Git uses the Windows certificate store, where IT deploys the company root. Then verify the server side with curl ssl.sh/example.com.

FAQ

Can I ignore Schannel 36887 events in the System log?

Often yes. Internet-facing servers log many of them from scanners and old clients that fail negotiation. Investigate only when they coincide with a real failure, and use the alert code to see why.

Is it OK to use curl --ssl-no-revoke or http.schannelCheckRevoke=false?

Those options skip certificate revocation checks. They are a reasonable workaround when a corporate proxy blocks CRL/OCSP traffic and you trust the network, but the proper fix is allowing access to the CA's revocation URLs. Do not use them as a general default.

How do I make old .NET Framework apps use TLS 1.2?

Set SchUseStrongCrypto and SystemDefaultTlsVersions to 1 under HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 (and the WOW6432Node equivalent), or retarget the app to .NET Framework 4.7 or later, which uses the operating system defaults.

Sources

  1. Microsoft Learn: Schannel error codes for TLS and SSL alerts
  2. Microsoft Learn: TLS registry settings
  3. Microsoft Learn: TLS/SSL (Schannel SSP) overview
  4. RFC 8446 section 6: Alert protocol