golang/go · error
tls: received a session ticket with invalid lifetime
Error message
tls: received a session ticket with invalid lifetime
What it means
A TLS 1.3 client received a NewSessionTicket whose lifetime field exceeds maxSessionTicketLifetime (7 days, per RFC 8446 §4.6.1). The server is forbidden from advertising a ticket valid longer than seven days; doing so is an illegal_parameter alert condition.
Source
Thrown at src/crypto/tls/handshake_client_tls13.go:854
func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error {
if !c.isClient {
c.sendAlert(alertUnexpectedMessage)
return errors.New("tls: received new session ticket from a client")
}
if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
return nil
}
// See RFC 8446, Section 4.6.1.
if msg.lifetime == 0 {
return nil
}
lifetime := time.Duration(msg.lifetime) * time.Second
if lifetime > maxSessionTicketLifetime {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: received a session ticket with invalid lifetime")
}
if len(msg.label) == 0 {
c.sendAlert(alertDecodeError)
return errors.New("tls: received a session ticket with empty opaque ticket label")
}
// RFC 9001, Section 4.6.1
if c.quic != nil && msg.maxEarlyData != 0 && msg.maxEarlyData != 0xffffffff {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid early data for QUIC connection")
}
cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite)
if cipherSuite == nil || c.resumptionSecret == nil {
return c.sendAlert(alertInternalError)
}
View on GitHub (pinned to b6b368adc5)
Solutions
- Report the bug to the server operator; RFC 8446 caps ticket_lifetime at 7 days.
- If you control the server, set ticket lifetime to <= 604800 seconds (commonly 86400 for 24h).
- Continue without session resumption — the client aborts this ticket but can negotiate a fresh full handshake.
- If interoperating with a known-broken peer, file an upstream issue rather than suppressing the alert.
Example fix
// server-side fix (Go)
cfg := &tls.Config{
SessionTicketsDisabled: false,
// Go enforces maxSessionTicketLifetime internally; do not try to override.
}
// If using a custom ticket store, ensure issued tickets carry lifetime <= 7*24*time.Hour. Defensive patterns
Strategy: validation
Validate before calling
// Server-side: cap ticket lifetime at issuance to the RFC maximum. const maxLifetime = 7 * 24 * time.Hour // 604800s // Go enforces this; if you maintain a custom ticket store, never write a // ticket with lifetime > maxLifetime.
Try / catch
cfg := &tls.Config{ClientSessionCache: tls.NewClientSessionCache(0)}
// On handshake error:
if err != nil && strings.Contains(err.Error(), "invalid lifetime") {
// peer bug; report upstream, disable resumption against this host
cfg.ClientSessionCache = nil
} Prevention
- When implementing a custom NewSessionTicket issuer, hard-code lifetime <= 7 days.
- Document resumption expectations with peer operators.
- Run interop tests against known-good clients/servers.
When it happens
Trigger: handleNewSessionTicket computes lifetime = msg.lifetime seconds and compares against maxSessionTicketLifetime; if larger, it sends alertIllegalParameter. The peer server sent a ticket_lifetime greater than 604800 seconds.
Common situations: A misconfigured or non-compliant server (custom TLS stack, some older OpenSSL forks, or a testing harness) advertising oversized lifetimes. Legitimate servers cap at 7 days.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: received a session ticket with empty opaque ticket labe
- tls: received new session ticket from a client
- tls: server sent unrequested session ticket
- tls: server selected TLS 1.3 in a renegotiation
- tls: unexpected encrypted client hello extension in server h
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/f504094c92198208.
Report an issue: GitHub.