golang/go · error
tls: client using inappropriate protocol fallback
Error message
tls: client using inappropriate protocol fallback
What it means
RFC 7507 defines TLS_FALLBACK_SCSV (0x5600), a cipher value a client includes to signal an intentional version downgrade. If the server observes it AND the negotiated version (c.vers) is lower than the server's maximum supported version, the downgrade is treated as a possible attack and aborted with an inappropriate_fallback alert. This is a downgrade-attack defense.
Source
Thrown at src/crypto/tls/handshake_server_tls13.go:137
return errors.New("tls: client used the legacy version field to negotiate TLS 1.3")
}
// Abort if the client is doing a fallback and landing lower than what we
// support. See RFC 7507, which however does not specify the interaction
// with supported_versions. The only difference is that with
// supported_versions a client has a chance to attempt a [TLS 1.2, TLS 1.4]
// handshake in case TLS 1.3 is broken but 1.2 is not. Alas, in that case,
// it will have to drop the TLS_FALLBACK_SCSV protection if it falls back to
// TLS 1.2, because a TLS 1.3 server would abort here. The situation before
// supported_versions was not better because there was just no way to do a
// TLS 1.4 handshake without risking the server selecting TLS 1.3.
for _, id := range hs.clientHello.cipherSuites {
if id == TLS_FALLBACK_SCSV {
// Use c.vers instead of max(supported_versions) because an attacker
// could defeat this by adding an arbitrary high version otherwise.
if c.vers < c.config.maxSupportedVersion(roleServer, c.quic != nil) {
c.sendAlert(alertInappropriateFallback)
return errors.New("tls: client using inappropriate protocol fallback")
}
break
}
}
if len(hs.clientHello.compressionMethods) != 1 ||
hs.clientHello.compressionMethods[0] != compressionNone {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: TLS 1.3 client supports illegal compression methods")
}
hs.hello.random = make([]byte, 32)
if _, err := io.ReadFull(c.config.rand(), hs.hello.random); err != nil {
c.sendAlert(alertInternalError)
return err
}
if len(hs.clientHello.secureRenegotiation) != 0 {View on GitHub (pinned to b6b368adc5)
Solutions
- Fix the root cause preventing the higher version (middlebox/firewall blocking TLS 1.3, broken TLS 1.3 implementation on either side)
- If the server genuinely only supports the lower version, ensure the client does not send TLS_FALLBACK_SCSV
- Verify tls.Config max supported version is what you intend (don't accidentally cap it below the client's offer)
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify your server supports the version the client wants to fall back from. maxVer := cfg.maxSupportedVersion(roleServer, false) // conceptual _ = maxVer // ensure it is not artificially capped
Try / catch
if err := tlsConn.Handshake(); err != nil {
if strings.Contains(err.Error(), "inappropriate protocol fallback") {
// Likely a middlebox blocking the higher version, or an attack.
log.Printf("downgrade/fallback rejected from %v: %v", remote, err)
}
c.Close()
return
} Prevention
- Investigate the network path: middleboxes that block TLS 1.3 cause clients to fall back and trip this guard
- Do not silence this alert — it is a downgrade-attack defense
- Confirm tls.Config.MaxVersion is not accidentally set below TLS 1.3
When it happens
Trigger: The client's cipher suites include TLS_FALLBACK_SCSV while c.vers < server's maxSupportedVersion. E.g., a client retry loop that steps down from TLS 1.3 to TLS 1.2 and tags the retry with FALLBACK_SCSV, hitting a server that genuinely supports TLS 1.3.
Common situations: Client libraries that auto-retry with version downgrade + FALLBACK_SCSV (Chrome, Firefox, some HTTP clients); a firewall or middlebox blocking TLS 1.3 so the client falls back; or an active attacker injecting SCSV to probe downgrade behavior.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: downgrade attempt detected, possibly due to a MitM atta
- tls: invalid server key share
- tls: invalid signature by the server certificate: {err}
- tls: invalid server finished hash
- tls: server selected ML-DSA with TLS version < 1.3
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/ff6316ee2b6ed294.
Report an issue: GitHub.