golang/go · error
tls: failed to write to key log:
Error message
tls: failed to write to key log:
What it means
If Config.KeyLogWriter is non-nil, after deriving the master secret Go calls writeKeyLog(keyLogLabelTLS12, hello.random, masterSecret) which writes '<label> <client_random> <secret>\n' to the writer. If Write returns an error, the handshake is aborted with alertInternalError and this message wrapping the underlying error.
Source
Thrown at src/crypto/tls/handshake_client.go:787
if hs.serverHello.extendedMasterSecret {
c.extMasterSecret = true
hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
hs.finishedHash.Sum())
} else {
if fips140tls.Required() {
if fips140ems.Value() != "0" {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: FIPS 140-3 requires the use of Extended Master Secret")
}
fips140ems.IncNonDefault()
}
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
hs.hello.random, hs.serverHello.random)
}
if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: failed to write to key log: " + err.Error())
}
if chainToSend != nil && len(chainToSend.Certificate) > 0 {
certVerify := &certificateVerifyMsg{}
key, ok := chainToSend.PrivateKey.(crypto.Signer)
if !ok {
c.sendAlert(alertInternalError)
return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
}
if c.vers >= VersionTLS12 {
signatureAlgorithm, err := selectSignatureScheme(c.vers, chainToSend, certReq.supportedSignatureAlgorithms)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
sigType, sigHash, err := typeAndHashFromSignatureScheme(signatureAlgorithm)View on GitHub (pinned to b6b368adc5)
Solutions
- Point Config.KeyLogWriter at a writable path on a volume with adequate free space.
- If logging is best-effort, wrap the writer so Write never returns an error (log the failure out-of-band instead of failing the handshake).
- Set Config.KeyLogWriter to nil in production unless you actively need to debug.
Example fix
// before: a writer whose error aborts the handshake
cfg := &tls.Config{KeyLogWriter: f} // f may fail
// after: swallow write errors so the handshake never breaks
type safeWriter struct{ w io.Writer }
func (s safeWriter) Write(p []byte) (int, error) {
n, err := s.w.Write(p)
if err != nil { log.Printf("keylog write failed: %v", err); return len(p), nil }
return n, nil
}
cfg := &tls.Config{KeyLogWriter: safeWriter{w: f}} Defensive patterns
Strategy: validation
Validate before calling
// Wrap the key log writer so it never fails the handshake.
type safeKeyLogWriter struct{ w io.Writer }
func (s safeKeyLogWriter) Write(p []byte) (int, error) {
n, err := s.w.Write(p)
if err != nil { log.Printf("keylog write failed: %v", err); return len(p), nil }
return n, nil
}
cfg.KeyLogWriter = safeKeyLogWriter{w: f} Type guard
func isKeyLogWriteError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "tls: failed to write to key log")
} Try / catch
if _, err := tls.Dial("tcp", addr, cfg); err != nil {
if isKeyLogWriteError(err) {
// The key log destination is broken; drop logging and retry.
cfg.KeyLogWriter = nil
_, err = tls.Dial("tcp", addr, cfg)
}
} Prevention
- Do not set Config.KeyLogWriter in production.
- Ensure the log path is on writable, non-full storage.
- Wrap the writer to swallow errors if logging is best-effort.
When it happens
Trigger: Config.KeyLogWriter points at a file on a full disk, a deleted file, a read-only filesystem, a closed pipe, or a custom Writer whose Write returns an error.
Common situations: SSLKEYLOGFILE path on a read-only mount in containers; disk full during long packet captures; key log redirected to a pipe whose consumer exited; file permissions wrong.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: either ServerName or InsecureSkipVerify must be specifi
- tls: invalid NextProtos value
- tls: NextProtos values too large
- tls: no supported versions satisfy MinVersion and MaxVersion
- tls: short read from Rand:
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/f6ebcbe8d7741c17.
Report an issue: GitHub.