Skip to content

objectstorage: fail a ranged read cut short by cancellation - #3049

Merged
Benjamin Elder (BenTheElder) merged 2 commits into
agent-substrate:mainfrom
cheftako:ranged-cancel-eof
Oct 22, 2026
Merged

Benjamin Elder (BenTheElder) merged 2 commits into
agent-substrate:mainfrom
cheftako:ranged-cancel-eof

Conversation

@cheftako

@cheftako Walter Fender (cheftako) commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Why is this needed?

When ctx was done, schedule closed ordered and Read returned io.EOF, even with bytes of the object still unread. A plain zstd stream cut at a frame boundary then decoded as a clean, truncated success. schedule now records the context's cause when it stops early, and Read returns it instead of io.EOF.

Fixes #3047

AI use: Claude assisted.

  • Tests pass
  • Docs updated

When ctx was done, schedule closed ordered and Read returned io.EOF,
even with bytes of the object still unread. A plain zstd stream cut at a
frame boundary then decoded as a clean, truncated success. Read now
returns the context's cause when it got fewer than size bytes.
Comment thread pkg/objectstorage/rangedget.go Outdated
size int64
// read is how many bytes Read has taken from ordered.
read int64
ctx context.Context

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ideally context should be passed in not placed in a structure. https://go.dev/blog/context-and-structs explains why this is a bad idea.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Agree, and claude has a suggestion that I like for avoiding that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 702186c with Ben's suggestion. rangedReader no longer holds ctx.

Comment thread pkg/objectstorage/rangedget.go Outdated
r.err = io.EOF
if r.read < r.size {
// schedule stops early only when ctx is done.
r.err = fmt.Errorf("ranged read stopped after %d of %d bytes: %w", r.read, r.size, context.Cause(r.ctx))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 nit 🟢 – This could drop both ctx and read from the struct, which also answers your note about ctx in a struct. schedule already knows when it stops early, so it can set e.g. r.stopErr = context.Cause(ctx) in its two ctx.Done() branches, and Read returns that instead of io.EOF once ordered is closed. The deferred close(r.ordered) happens before the receive that sees it closed, so reading the field is race-free.
https://go.dev/ref/mem#chan

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 702186c. schedule sets stopErr in both ctx.Done branches, and Read returns it once ordered is closed. ctx and the read counter are gone from rangedReader.

Comment thread pkg/objectstorage/rangedget.go Outdated
size int64
// read is how many bytes Read has taken from ordered.
read int64
ctx context.Context

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Agree, and claude has a suggestion that I like for avoiding that.

@BenTheElder Benjamin Elder (BenTheElder) added kind/bug Something isn't working / bugfixes area/storage labels Oct 21, 2026
schedule sets stopErr when ctx is done before every range is issued.
Read returns it once ordered is closed. This drops ctx and the byte
count from rangedReader.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

no claude, just me. this LGTM. thanks.

@BenTheElder
Benjamin Elder (BenTheElder) added this pull request to the merge queue Oct 22, 2026
Merged via the queue into agent-substrate:main with commit d7c074b Oct 22, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage kind/bug Something isn't working / bugfixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectstorage: cancelled ranged download ends in io.EOF instead of an error

2 participants