Skip to content

Client configured to use Zstd will try to decompress non-Zstd responses #483

Closed

Description

@dankmeme01

Describe the bug

When enabling Zstd compression, the Clickhouse client will add the accept-encoding: zstd header to tell the server that it can accept Zstd encoded bodies. However, HTTP defines this as a suggestion, so the server or any proxy in the middle does not have to comply.

In my case, I use Cloudflare as a proxy, which seems to not apply compression because the response is already small (87 bytes), but Clickhouse unconditionally tries to decompress the payload with Zstd, which fails due to it not being compressed:

clickhouse-rs/src/query.rs

Lines 296 to 297 in fcb8b02

let future = self.client.http.request(request);
Ok(Response::new(future, self.client.compression))

compression is then eventually passed to Decompress::new:

impl Chunks {
fn new(stream: Incoming, compression: Compression, exception_tag: Option<Box<[u8]>>) -> Self {
let stream = IncomingStream(stream);
let stream = Decompress::new(stream, compression);

Steps to reproduce

  1. Create a client with compression mode Compression::Zstd(_)
  2. Run a SELECT query against a clickhouse server with a proxy in-between that does not compress the response with Zstd
  3. The query errors with decompression error: Unknown frame descriptor

Expected behaviour

Clickhouse client should check the Content-Encoding header in the response and use the value in the header to decide whether the response is compressed, instead of assuming it's always Zstd.

Code example

let client = clickhouse::Client::default()
    // ... credential setup omitted ...
    .with_compression(clickhouse::Compression::zstd());

client.query("SELECT * FROM table").fetch_all().await?;

Configuration

Environment

  • Client version: 0.15.2
  • OS: Linux x64

ClickHouse server

  • ClickHouse Server version: 26.9.2.8

Activity

  1. abonander commented on Sep 30, 2026

    @abonander
    Contributor

    Great news! I've coincidentally fixed this in #482 as well since it now chooses the decoder based on the Content-Encoding header, because I foresaw this exact kind of issue 🤣.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions