jackc/pgx · error

tls error on cancel connection

Error message

tls error on cancel connection: %w

What it means

While establishing the encrypted cancellation connection, the TLS handshake failed. The wrapped error is the crypto/tls failure. The primary connection is unaffected; only the cancel request could not be sent securely.

Solutions

  1. Check the wrapped TLS error for the specific handshake failure
  2. Verify TLS configuration on both client and server
  3. If cancel is best-effort, ignore the error and let the query finish
  4. Retry the cancellation request
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at pgconn/pgconn.go:1145 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /api/errors/c552bc672e8c0111. Report an issue: GitHub.

Appendix: source

Thrown at pgconn/pgconn.go:1145

	if ctx != context.Background() {
		contextWatcher := ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: cancelConn})
		contextWatcher.Watch(ctx)
		defer contextWatcher.Unwatch()
	}

	// If the primary connection is encrypted, encrypt the cancel connection the same way so the
	// backend pid and secret key are not exposed to a passive network observer. This mirrors libpq's
	// PQcancelCreate (PG17+), which reuses the original connection's sslmode/gssencmode for the
	// cancel connection. The legacy unencrypted path is still used when the primary connection is
	// plaintext (e.g. unix sockets or sslmode=disable).
	if pgConn.tlsConfig != nil {
		var tlsCancelConn net.Conn
		if pgConn.config.SSLNegotiation == "direct" {
			tlsCancelConn = tls.Client(cancelConn, pgConn.tlsConfig)
		} else {
			tlsCancelConn, err = startTLS(cancelConn, pgConn.tlsConfig)
			if err != nil {
				return fmt.Errorf("tls error on cancel connection: %w", err)
			}
		}
		cancelConn = tlsCancelConn
		defer cancelConn.Close()
	}

	buf := make([]byte, 12+len(pgConn.secretKey))
	binary.BigEndian.PutUint32(buf[0:4], uint32(len(buf)))
	binary.BigEndian.PutUint32(buf[4:8], 80877102)
	binary.BigEndian.PutUint32(buf[8:12], pgConn.pid)
	copy(buf[12:], pgConn.secretKey)

	if _, err := cancelConn.Write(buf); err != nil {
		return fmt.Errorf("write to connection for cancellation: %w", err)
	}

	// Wait for the cancel request to be acknowledged by the server.
	// It copies the behavior of the libpq: https://github.com/postgres/postgres/blob/REL_16_0/src/interfaces/libpq/fe-connect.c#L4946-L4960

View on GitHub (pinned to ec1a0befd2)