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.

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.

Appendix: 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)