fix(storage): preserve ReadParts errors across keepalive responses

ReadPartsHandler completed its keepalive stream before reporting storage failures, then tried to write an ordinary error response after the body was already owned. Clients consequently decoded the error text as msgpack and lost the real failure.

Send failures through the keepalive completion channel and mark success only after ReadParts returns cleanly, preserving the existing wire framing and error identity.

Co-authored-by: ChatGPT <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Feng Ruohang
2026-08-04 22:42:56 +08:00
parent b6f70ab085
commit 1af351a702
4 changed files with 42 additions and 19 deletions
+3 -3
View File
@@ -83,9 +83,9 @@ type guardedStorage struct {
// short paths used here, so " " and "..." reach the syscall as an empty
// component. On Unix they are ordinary filenames and legal object keys.
//
// Note the second point is reasoned from documented Win32 behaviour, not from a
// Note the second point is reasoned from documented Win32 behavior, not from a
// Windows test run: CI is Linux-only, so TestIsVolumeRootAliasIsPlatformCorrect
// pins both branches of the predicate rather than the syscall behaviour itself.
// pins both branches of the predicate rather than the syscall behavior itself.
func isVolumeRootAlias(p string) bool {
return isVolumeRootAliasOn(p, runtime.GOOS == globalWindowsOSName)
}
@@ -125,7 +125,7 @@ func isVolumeRootAliasOn(p string, windows bool) bool {
// for them, so they say nothing about whether the metadata is sound.
//
// This is the boundary check; ShardFileSize's own zero-value guard stays as the
// last line of defence against a panic.
// last line of defense against a panic.
func guardErasureParams(fi FileInfo) error {
// Negative sizes share their rule with the storage layer, which also has to
// cope with metadata already on disk; keep the two from drifting apart by