- PowerShell
- Exact text checked with the real tool
Could not establish trust relationship for the SSL/TLS secure channel
Also seen in: Windows PowerShell 5.1, Invoke-WebRequest, Invoke-RestMethod, .NET Framework, WebClient, HttpWebRequest
In one sentence
Windows PowerShell or a .NET Framework app rejected the server's certificate: the root is not trusted here, the chain is incomplete, the certificate expired, or the name is wrong.
Where you see it
In Windows PowerShell 5.1 (Invoke-WebRequest, Invoke-RestMethod, System.Net.WebClient) and in .NET Framework applications that use HttpWebRequest:
Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS
secure channel.
At line:1 char:1
+ Invoke-WebRequest -Uri https://api.example.com/ -UseBasicParsing
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
This is the TrustFailure status of a WebException; the text is in the .NET Framework reference source. The inner exception says more:
$Error[0].Exception.InnerException.Message
The remote certificate is invalid according to the validation procedure.
PowerShell 7 runs on modern .NET and reports the same problem differently; see The remote certificate is invalid according to the validation procedure.
What it means
.NET Framework asked Windows to check the server’s certificate, and Windows said no. Windows builds the certificate chain from the server’s certificate up to a root certificate in the machine’s Trusted Root Certification Authorities store, and checks the dates and the host name. Any failure gives this one message. To fix it, find out which check failed.
Find the exact reason
Windows PowerShell keeps the certificate of the failed connection, so you can ask Windows to build the chain and show its status, without switching anything off:
$req = [System.Net.HttpWebRequest]::Create('https://api.example.com/')
try { $req.GetResponse().Dispose() } catch { }
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($req.ServicePoint.Certificate)
$chain = [System.Security.Cryptography.X509Certificates.X509Chain]::new()
$chain.Build($cert)
$chain.ChainStatus | Format-List Status, StatusInformation
$cert | Format-List Subject, Issuer, NotAfter, DnsNameList
False
Status : PartialChain
StatusInformation : A certificate chain could not be built to a trusted root authority.
Status : NotTimeValid
StatusInformation : A required certificate is not within its validity period when verifying against the current system
clock or the timestamp in the signed file.
Status : RevocationStatusUnknown
StatusInformation : The revocation function was unable to check revocation for the certificate.
Status : OfflineRevocation
StatusInformation : The revocation function was unable to check revocation because the revocation server was offline.
Subject : CN=api.example.com
Issuer : CN=Example Issuing CA, O=Example CA
NotAfter : 2026-04-01 2:00:00 AM
DnsNameList : {api.example.com}
Look for UntrustedRoot, PartialChain or NotTimeValid. RevocationStatusUnknown and OfflineRevocation can also appear, because this check asks Windows to look up revocation. If the chain is fine, compare DnsNameList with the host name you used.
Likely causes
UntrustedRoot or PartialChain: the root is not trusted here
Internal servers often use a company CA; a TLS-inspection proxy re-signs public sites with its own root. Both roots must be in the Windows store. Fix: ask IT to deploy the root through Group Policy or Intune, or import it yourself (administrator):
Import-Certificate -FilePath .\corp-root.cer -CertStoreLocation Cert:\LocalMachine\Root
See How to trust a private root CA on Windows and How to work behind a TLS-inspecting corporate proxy, safely.
On machines without internet access, a public root can also be missing: Windows downloads trusted roots from Windows Update when it needs them, and disconnected machines must get them another way (Microsoft: trusted roots in disconnected environments).
PartialChain: the server does not send its intermediate
Windows can download a missing intermediate itself, but not on a network that blocks it. Confirm with openssl s_client -showcerts (Git for Windows includes OpenSSL): one certificate means the intermediate is missing. Fix the server: How to build the full chain file your server needs. On IIS, import the intermediate into the computer’s “Intermediate Certification Authorities” store.
NotTimeValid: a certificate expired
Renew the server’s certificate and reload the service, or correct the client’s clock (w32tm /resync).
The name does not match
Calling a server by its IP address or a short name that is not in the certificate fails too. Use the name in DnsNameList, or add the name you need to the certificate.
Check yours
Paste the certificates the server sends (from openssl s_client -showcerts, or exported from the browser). The checker shows a missing intermediate and names the root the chain needs.
Learn why
- Who do we trust? CAs, trust stores and self-signed certificates: the Windows store and other stores.
- Certificate chains and path validation: how Windows builds the chain.
- Related: schannel: SEC_E_UNTRUSTED_ROOT in git and curl on Windows.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.