golang/go · error

tls: server resumed a session with a different cipher suite

Error message

tls: server resumed a session with a different cipher suite

What it means

A resumed session must reuse the original cipher suite. If hs.session.cipherSuite != hs.suite.id the server resumed with a different suite than the original handshake, which TLS forbids and aborts with alertHandshakeFailure.

Source

Thrown at src/crypto/tls/handshake_client.go:943

		c.sendAlert(alertUnsupportedExtension)
		return false, err
	}
	c.clientProtocol = hs.serverHello.alpnProtocol

	c.scts = hs.serverHello.scts

	if !hs.serverResumedSession() {
		return false, nil
	}

	if hs.session.version != c.vers {
		c.sendAlert(alertHandshakeFailure)
		return false, errors.New("tls: server resumed a session with a different version")
	}

	if hs.session.cipherSuite != hs.suite.id {
		c.sendAlert(alertHandshakeFailure)
		return false, errors.New("tls: server resumed a session with a different cipher suite")
	}

	// RFC 7627, Section 5.3
	if hs.session.extMasterSecret != hs.serverHello.extendedMasterSecret {
		c.sendAlert(alertHandshakeFailure)
		return false, errors.New("tls: server resumed a session with a different EMS extension")
	}

	// Restore master secret and certificates from previous state
	hs.masterSecret = hs.session.secret
	c.extMasterSecret = hs.session.extMasterSecret
	c.peerCertificates = hs.session.peerCertificates
	c.verifiedChains = hs.session.verifiedChains
	c.ocspResponse = hs.session.ocspResponse
	// Let the ServerHello SCTs override the session SCTs from the original
	// connection, if any are provided.
	if len(c.scts) == 0 && len(hs.session.scts) != 0 {
		c.scts = hs.session.scts

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Rotate the server's session ticket key to invalidate inconsistent cached state.
  2. Upgrade the server TLS stack.
  3. Disable client-side session resumption (SessionTicketsDisabled = true) if the server is unfixable.

Example fix

cfg := &tls.Config{SessionTicketsDisabled: true}
Defensive patterns

Strategy: fallback

Type guard

func isResumptionCipherMismatch(err error) bool {
    return err != nil && strings.Contains(err.Error(), "server resumed a session with a different cipher suite")
}

Try / catch

if _, err := tls.Dial("tcp", addr, cfg); err != nil {
    if isResumptionCipherMismatch(err) {
        cfg.SessionTicketsDisabled = true
        cfg.ClientSessionCache = nil
        _, err = tls.Dial("tcp", addr, cfg)
    }
}

Prevention

When it happens

Trigger: Server resuming a session but picking a different cipher suite; ticket corruption; server bug in resumption state binding.

Common situations: Misconfigured server resumption cache; rare.

Understand the failure class

Related errors


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