pgx icon indicating copy to clipboard operation
pgx copied to clipboard

Wrong host in ConnectError

Open ndtretyak opened this issue 1 year ago • 1 comments

Describe the bug When a connection string contains multiple hosts, the Config.Host field is populated with the first host, while the remaining hosts are treated as FallbackConfigs. The connect function, which accepts both Config and FallbackConfig to establish a connection, uses the Host and Port from the FallbackConfig.

https://github.com/jackc/pgx/blob/da6f2c98f2664b215b40b1606551fdfcc7f3ea5c/pgconn/pgconn.go#L283

However, in the event of a connection error, the default Config is used, leading to a mismatch between the error message (which contains the IP address of the host we attempted to connect to) and the Host and Port from a different host.

https://github.com/jackc/pgx/blob/da6f2c98f2664b215b40b1606551fdfcc7f3ea5c/pgconn/pgconn.go#L286

To Reproduce Steps to reproduce the behavior:

package main

import (
	"context"
	"log"

	"github.com/jackc/pgx/v5"
)

const url = "postgresql://user:password@localhost:1234,127.0.0.1:5678/database"

func main() {
	conn, err := pgx.Connect(context.Background(), url)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close(context.Background())
}

Expected behavior The error message should match the host we attempted to connect to. Possible outcome are

  • host=localhost ... dial tcp 127.0.0.1:1234
  • host=127.0.0.1 ... dial tcp 127.0.0.1:5678

Actual behavior The error message contains a mismatched host and port

2024/03/06 11:13:07 failed to connect to `host=localhost user=user database=database`: dial error (dial tcp 127.0.0.1:5678: connect: connection refused)
exit status 1

Additional context It would be more informative to return an error group containing connection errors for all attempted hosts. This would be particularly useful when target_session_attrs=primary is used and a connection to the primary cannot be established. In this case we can get a useless server is in standby mode while connecting to the other node.

ndtretyak avatar Mar 06 '24 10:03 ndtretyak

It would be more informative to return an error group containing connection errors for all attempted hosts.

As of Go 1.20 we now have a better way of returning multiple errors. That's a reasonable change. 👍

jackc avatar Mar 09 '24 17:03 jackc

I've added multiple error returns for connection failures in 8db971660e43a944c777d5e4fcfcb7885acb7566.

For example, the following connection string:

host=localhost,127.0.0.1,foo.invalid port=1,2,3

Will now return an error like the following:

    failed to connect to `user=postgres database=pgx_test`:
            lookup foo.invalid: no such host
            [::1]:1 (localhost): dial error: dial tcp [::1]:1: connect: connection refused
            127.0.0.1:1 (localhost): dial error: dial tcp 127.0.0.1:1: connect: connection refused
            127.0.0.1:2 (127.0.0.1): dial error: dial tcp 127.0.0.1:2: connect: connection refused

jackc avatar May 11 '24 19:05 jackc