golang/go · error
tls: either ServerName or InsecureSkipVerify must be specifi
Error message
tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config
What it means
Thrown by makeClientHello when the tls.Config has an empty ServerName field and InsecureSkipVerify is false. The TLS client requires either a server hostname (for SNI extension and certificate hostname validation) or an explicit opt-in to skip certificate verification. This is a mandatory configuration check that prevents accidental insecure connections.
Source
Thrown at src/crypto/tls/handshake_client.go:47
"time"
)
type clientHandshakeState struct {
c *Conn
ctx context.Context
serverHello *serverHelloMsg
hello *clientHelloMsg
suite *cipherSuite
finishedHash finishedHash
masterSecret []byte
session *SessionState // the session being resumed
ticket []byte // a fresh ticket received during this handshake
}
func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echClientContext, error) {
config := c.config
if len(config.ServerName) == 0 && !config.InsecureSkipVerify {
return nil, nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
}
nextProtosLength := 0
for _, proto := range config.NextProtos {
if l := len(proto); l == 0 || l > 255 {
return nil, nil, nil, errors.New("tls: invalid NextProtos value")
} else {
nextProtosLength += 1 + l
}
}
if nextProtosLength > 0xffff {
return nil, nil, nil, errors.New("tls: NextProtos values too large")
}
supportedVersions := config.supportedVersions(roleClient, c.quic != nil)
if len(supportedVersions) == 0 {
return nil, nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion")
}View on GitHub (pinned to b6b368adc5)
Solutions
- Set config.ServerName to the hostname you are connecting to (e.g., "example.com")
- Use tls.Dial instead of tls.Client — tls.Dial auto-sets ServerName from the host portion of the address
- If connecting by IP, set ServerName to the IP string literal so certificate validation can proceed
- Only in development/testing, set InsecureSkipVerify=true (never use in production — it disables all certificate verification)
Example fix
// before
config := &tls.Config{}
conn, err := tls.Dial("tcp", "example.com:443", config)
// ServerName is empty, InsecureSkipVerify is false → error
// after — tls.Dial auto-sets ServerName from host
conn, err := tls.Dial("tcp", "example.com:443", nil)
// or set explicitly:
config := &tls.Config{ServerName: "example.com"}
conn, err := tls.Dial("tcp", "example.com:443", config) Defensive patterns
Strategy: validation
Validate before calling
func validateClientTLSConfig(config *tls.Config) error {
if len(config.ServerName) == 0 && !config.InsecureSkipVerify {
return errors.New("tls.Config must set ServerName or InsecureSkipVerify")
}
return nil
}
// Usage:
// if err := validateClientTLSConfig(config); err != nil {
// log.Fatal(err)
// }
// conn, err := tls.Dial("tcp", addr, config) Type guard
// Type guard to check if a Config is safe for client use
func hasValidClientIdentity(config *tls.Config) bool {
return len(config.ServerName) > 0 || config.InsecureSkipVerify
} Try / catch
// Prefer pre-dial validation over try-catch:
//
// if !hasValidClientIdentity(config) {
// config.ServerName = hostnameFromAddress(addr)
// }
// conn, err := tls.Dial("tcp", addr, config)
// if err != nil {
// // handle connection error
// } Prevention
- Always set ServerName in tls.Config for client connections
- Use tls.Dial (not tls.Client) which auto-sets ServerName from the address host
- Never use InsecureSkipVerify in production code
- Write a Config builder/constructor that enforces ServerName as a required parameter
When it happens
Trigger: Calling tls.Dial, tls.DialWithDialer, or tls.Client with a tls.Config where ServerName is an empty string (or unset) and InsecureSkipVerify is false (the default).
Common situations: Creating a custom tls.Config with &tls.Config{} and forgetting to set ServerName. Dialing by IP address without setting ServerName to the IP string. Copying a Config struct and clearing ServerName. Using tls.Client directly (which does not auto-populate ServerName from the address, unlike tls.Dial).
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: invalid NextProtos value
- tls: NextProtos values too large
- tls: no supported versions satisfy MinVersion and MaxVersion
- tls: short read from Rand:
- tls: no supported key exchange methods (CurveIDs)
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/bd6f4c72edad9125.
Report an issue: GitHub.