On slower networks "Invalid Error: Failed to decompress GZIP block: data error" for files that work on faster networks
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 60
- Forks
- 100
- Avg merge
- 1h 50m
- Merged PRs (30d)
- 25
Description
Hi,
I noticed that some queries over parquet files can error out with Invalid Error: Failed to decompress GZIP block: data error when executed on slower networks.
Same query works fine on a faster network.
It also works fine when duckdb was limited to using a single thread
Since I'm not a C++ developer, I used Claude (Fable) to look into this.
This is the gist of it (I've highlighted all Claude contributions quoted)
http_timeout(default 30 s) is enforced asCURLOPT_TIMEOUT, a cap on total transfer time. On a slow connection a range GET can exceed it, and curl kills the transfer mid-body — after the206status line and part of the body have already arrived. The client delivers the partial body to the read buffer anyway, retries fail the same way, and the final failed response is returned to the caller rather than thrown.TryRangeRequest(src/httpfs.cpp:505, unchanged onmain) then accepts it:
if (res->Success() || res->status == HTTPStatusCode::PartialContent_206 || ...) {
return true; // partial buffer accepted as a complete read
}
// HasRequestError() only consulted below
A
206status line only means the server accepted the range request — it can't promise the body arrived. The check answers a transport-layer question with an HTTP-layer field. Two extra details:
- On current core every clean 2xx already has
Success()==true, so the|| status == 206clause (a workaround per its TODO comment) matches only failed transfers.try_requestcomes fromHTTPFileHandle::auto_fallback_to_full_file_download(httpfs.hpp:91), hardcodedtrueand never synced fromSET auto_fallback_to_full_download— no setting can surface the failure (verified, scenario D).
As far as I can tell #336 is already dealing with the root cause (killing the transfer), but it seems that the check should also make sure there is no actual request error before returning true.
- if (res->Success() || res->status == HTTPStatusCode::PartialContent_206 ||
- res->status == HTTPStatusCode::Accepted_202) {
+ if ((res->Success() || res->status == HTTPStatusCode::PartialContent_206 ||
+ res->status == HTTPStatusCode::Accepted_202) &&
+ !res->HasRequestError()) {
The rejected response falls through to the existing error handling, so the
RangeRequestNotSupported→ full-download fallback is preserved. Companions worth doing: sync theauto_fallback_to_full_downloadsetting onto the handle; don't deliver partial bodies tocontent_handleron curl errors.
Hope this is helpful.
I can also share a repro script that can deterministically reproduce the error.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/httpfs.cpp around TryRangeRequest at line 505 and read HTTPFileHandle::auto_fallback_to_full_file_download in httpfs.hpp:91. Reproduce with a parquet query on a slower network and compare multi-threaded versus single-threaded behavior. Done means failed range transfers are handled as errors rather than accepted as complete responses, while the existing fallback behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 62/100