Skip to content

fix(rs-client): Validate resumable upload streams through EOF - #754

Merged
vjeranc merged 6 commits into
mainfrom
fix/resumable-stream-completion
Nov 3, 2026
Merged

vjeranc merged 6 commits into
mainfrom
fix/resumable-stream-completion

Conversation

@vjeranc

@vjeranc vjeranc commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Resumable uploads can return success after sending the declared byte count without observing a subsequent source error. For example, a gzip decoder can produce all expected bytes before reporting a checksum failure.

Validate the exact length and successful source EOF before sending the final chunk. Earlier chunks continue streaming immediately; zero-length sources are validated before the request. The same contract applies to put_stream and put_read, while buffered uploads retain their existing path.

The first commit adds the regression test and intentionally fails against the previous implementation. The second adds the fix and focused length and streaming tests.

Discovered in getsentry/relay#6572. Relay can remove its local workaround after consuming a fixed client release.

Refs FS-596

Changelog Entry

Reject resumable uploads with incomplete or invalid source streams.

vjeranc and others added 2 commits November 3, 2026 14:27
Exercise sources that yield the declared length and then fail, through both stream and reader uploads, including empty uploads.

Co-authored-by: Codex <noreply@openai.com>
HTTP can stop polling once Content-Length bytes have been sent, leaving source completion errors unobserved. Check the declared length and successful EOF before yielding the final chunk, and validate empty uploads before sending the request. Share the check between stream and reader uploads while preserving the buffered-body path.

Co-authored-by: Codex <noreply@openai.com>
@vjeranc
vjeranc requested a review from a team as a code owner November 3, 2026 13:29
@linear-code

linear-code Bot commented Nov 3, 2026

Copy link
Copy Markdown

FS-596

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Semver Impact of This PR

This PR lands in these workspaces:

  • clients/rust: 🟢 Patch (bug fixes)
📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes

  • Reject resumable uploads with incomplete or invalid source streams. by vjeranc and codex in #754

🤖 This preview updates automatically when you update the PR.

@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.09091% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.82%. Comparing base (1d3a0e8) to head (c1e758a).

Files with missing lines Patch % Lines
clients/rust/src/resumable.rs 99.09% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #754      +/-   ##
==========================================
+ Coverage   91.80%   91.82%   +0.02%     
==========================================
  Files         118      118              
  Lines       22469    22567      +98     
==========================================
+ Hits        20628    20723      +95     
- Misses       1841     1844       +3     
Components Coverage Δ
Rust Backend 94.80% <ø> (ø)
Rust Client 88.36% <99.09%> (+0.59%) ⬆️
Python Client 93.88% <ø> (ø)

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-authored-by: Codex <noreply@openai.com>
@vjeranc
vjeranc marked this pull request as draft November 3, 2026 13:38
vjeranc and others added 2 commits November 3, 2026 14:40
Keep each stream with its declared length and derive buffer lengths from their bytes. Move body construction and source validation into UploadChunk so the request builder no longer stores an independent length or selects validation by body type.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
@vjeranc
vjeranc marked this pull request as ready for review November 3, 2026 13:46
@lcian

lcian commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Leaving the full review to @jan-auer, but wanted to call out the following: even with this fix, the server could persist a prefix of the body that has already been sent, which in the case you mentioned (a Gzip decoder that errors with a checksum failure) could likely contain corrupt data.

@jan-auer jan-auer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that when something like a checksum error occurs at the very end, the entire upload is still online and waiting for completion or cancellation. Whether the upload can be resumed remains with the caller, so there's nothing we can do in the client with this.

Comment thread clients/rust/src/resumable.rs Resolved
Co-authored-by: Codex <noreply@openai.com>
@vjeranc

vjeranc commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

Yes, I agree that relay should handle the cleanup.

@vjeranc
vjeranc merged commit ed881d7 into main Nov 3, 2026
26 checks passed
@vjeranc
vjeranc deleted the fix/resumable-stream-completion branch November 3, 2026 21:00
jan-auer added a commit that referenced this pull request Nov 4, 2026
* origin/main:
  feat(clients): Send Content-Length for uploads of known size (#751)
  fix(stresstest): Compare read payloads without buffering them in memory (#753)
  ci(release): Bump craft to 3.9.0 (#760)
  fix(rs-client): Validate resumable upload streams through EOF (#754)

# Conflicts:
#	clients/rust/src/resumable.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants