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 the

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Disable or fix OCSP stapling on the server so status_request is consistently advertised.
  2. Remove any intermediary that injects CertificateStatus without negotiating it.
  3. 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

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

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/396bc8845e753c6f. Report an issue: GitHub.