Skip to content

Antalya-26.6: PostgreSQL wire protocol advertises non-numeric server_version, breaks Npgsql clients #2033

Description

@CarlosFelipeOR

Type of problem

Bug report — something's broken

Describe the situation

Any Npgsql-based .NET client (Npgsql ≥ 9) connecting to Altinity ClickHouse via the PostgreSQL wire port fails at NpgsqlConnection.Open() with:

Error: Version string portion was too short or too long. (Parameter 'input')

This is the exception System.Version.Parse throws when the input has more than 4 dot-separated components or the last component is non-numeric.

The server advertises server_version verbatim from VERSION_STRING:

  • src/Server/PostgreSQLHandler.cpp:387
    message_transport->send(PostgreSQLProtocol::Messaging::ParameterStatus("server_version", VERSION_STRING));
  • On antalya-26.6 (cmake/autogenerated_versions.txt): VERSION_STRING = 26.6.1.20000.altinityantalya — 5 components, 5th non-numeric.

Upstream never hits this because upstream VERSION_STRING is always ≤ 4 purely numeric components (26.6.1.N-lts etc.). The .altinityantalya (also .altinitystable, .altinitytest) suffix is fork-specific, so this is an Altinity-only wire-protocol incompatibility with the most widely used .NET Postgres client.

Detected via test_postgresql_protocol/test.py::test_dotnet_client on antalya-26.6: 0 OK / 8 FAIL in gh-data.checks — the test was re-added via the un-revert d2122fc6ef0 "Revert 'Revert Support C# client in postgres protocol'" and has never passed on our fork.

How to reproduce the behavior

Environment

  • Branch: antalya-26.6 (SHA 9ddb8373074468f3517ad004ee45e8e9135a7911)
  • Client: Npgsql 9.0.3 on .NET 8 (see ci/docker/integration/mysql_dotnet_client/pg/testapp.csproj)

Steps

Reproduce via the integration test:

pytest test_postgresql_protocol/test.py::test_dotnet_client

Log reference

Failing run: https://github.com/Altinity/ClickHouse/actions/runs/28911185989/job/85897143977

Job log: https://altinity-build-artifacts.s3.amazonaws.com/REFs/antalya-26.6/9ddb8373074468f3517ad004ee45e8e9135a7911/integration_tests_amd_msan_4_6/job.log

Relevant excerpt:

Command:[docker exec roottestpostgresqlprotocol-gw0-postgresql-dotnet-client-1 bash -c cd /pg_testapp && dotnet run -- --host node --port 5433 --username default --password 123]
Stdout:Error: Version string portion was too short or too long. (Parameter 'input')
FAILED test_postgresql_protocol/test.py::test_dotnet_client - assert False

Expected behavior

conn.Open() succeeds; the test's dotnet.reference output (Connection successful! / Result: 1 / Content: id = 16, name = bool ...) is produced.

Actual behavior

Connection setup aborts with Version string portion was too short or too long. (Parameter 'input') before any query runs. Applies to every Npgsql ≥ 9 client, not only the test.

Suggested fix

Sanitize the value passed to ParameterStatus("server_version", ...) at src/Server/PostgreSQLHandler.cpp:387 so it is a 3–4-component purely numeric string. Options in increasing order of change:

  1. Send VERSION_STRING_SHORT (already computed as MAJOR.MINOR in cmake/version.cmake).
  2. Compose MAJOR.MINOR.PATCH.TWEAK from the existing CMake numeric vars, dropping VERSION_FLAVOUR.
  3. Strip everything from the first non-[0-9.] character in VERSION_STRING before sending.

Any of these keeps the wire value parseable by System.Version while preserving useful version detail. Option 2 is closest to what upstream naturally emits.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions