golang/go · error
tls: received unexpected CertificateStatus message
Error message
tls: received unexpected CertificateStatus message
What it means
Per RFC 4366, the server MAY send a CertificateStatus message only if it included the status_request extension with empty data in the ServerHello. The client tracks that via hs.serverHello.ocspStapling; if a CertificateStatus message arrives while that flag is false, the server is violating the protocol and the handshake fails with alertUnexpectedMessage.
Source
Thrown at src/crypto/tls/handshake_client.go:670
}
msg, err = c.readHandshake(&hs.finishedHash)
if err != nil {
return err
}
cs, ok := msg.(*certificateStatusMsg)
if ok {
// RFC4366 on Certificate Status Request:
// The server MAY return a "certificate_status" message.
if !hs.serverHello.ocspStapling {
// If a server returns a "CertificateStatus" message, then the
// server MUST have included an extension of type "status_request"
// with empty "extension_data" in the extended server hello.
c.sendAlert(alertUnexpectedMessage)
return errors.New("tls: received unexpected CertificateStatus message")
}
c.ocspResponse = cs.response
msg, err = c.readHandshake(&hs.finishedHash)
if err != nil {
return err
}
}
if c.handshakes == 0 {
// If this is the first handshake on a connection, process and
// (optionally) verify the server's certificates.
if err := c.verifyServerCertificate(certMsg.certificates); err != nil {
return err
}
} else {
// This is a renegotiation handshake. We require that theView on GitHub (pinned to b6b368adc5)
Solutions
- Disable or fix OCSP stapling on the server so status_request is consistently advertised.
- Remove any intermediary that injects CertificateStatus without negotiating it.
- Capture the handshake to confirm which side originates the spurious message.
Defensive patterns
Strategy: try-catch
Type guard
func isUnexpectedCertStatus(err error) bool {
return err != nil && strings.Contains(err.Error(), "received unexpected CertificateStatus message")
} Try / catch
if _, err := tls.Dial("tcp", addr, cfg); err != nil {
if isUnexpectedCertStatus(err) {
// Server bug; report to operator. Retrying will not help.
reportServerDefect(addr, err)
}
} Prevention
- Report server-side OCSP stapling defects to the operator.
- Capture the handshake to confirm the originator of the message.
When it happens
Trigger: Misbehaving server or OCSP-stapling proxy sending CertificateStatus without having advertised status_request in its ServerHello; corrupted ServerHello where the status_request extension was lost.
Common situations: Custom TLS stack with broken OCSP stapling logic; intermediate appliance injecting OCSP responses; rare for mainstream servers.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: server echoed TLS 1.3 compatibility session ID in TLS 1
- tls: server offered only incompatible point formats
- tls: missing signature_algorithms from TLS 1.2 peer
- tls: peer doesn't support any of the certificate's signature
- connection doesn't support Ed25519
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/396bc8845e753c6f.
Report an issue: GitHub.