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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions