Keep a pack-observer Scanner error from aborting the upload#84
Merged
Conversation
The observer tees the pack stream through a goroutine running packfile.Scanner. When that Scanner stopped early (a malformed pack, or content it couldn't parse), its deferred pr.Close() broke the pipe, so the next TeeReader write failed with io.ErrClosedPipe and surfaced from Read — aborting the live push, despite the documented "non-fatal for the upload" contract. Tee through a bestEffortWriter that absorbs write failures and always reports success, so a stopped observer can never turn into a failed upload. The bytes keep flowing to the server and the Scanner error remains available via ScannerError() for debugging. (This removes the spurious push failure, so there is no longer an unclassified error for executeBatched to mishandle.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: b7dda726e331
nodo
approved these changes
Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
packStreamObservertees the pack upload stream through a goroutine runningpackfile.Scanner. When that Scanner stopped early — a malformed pack, or content it couldn't parse —consume'sdefer pr.Close()broke the pipe. The nextio.TeeReaderwrite then failed withio.ErrClosedPipe, surfaced fromRead, and aborted the live push — directly contradicting the documented "non-fatal for the upload" contract. The resulting spurious error also wasn't classified as subdividable byexecuteBatched.Fix
Tee through a small
bestEffortWriterthat absorbs write failures and always reports success, so a stopped observer can never turn into a failed upload. The bytes keep flowing to the server; the Scanner error stays available viaScannerError()for debugging.Why the writer side, not the pipe lifecycle
observer.Close()is not reliably called in the bootstrap push flow (the error and success paths close the underlyingpackReader, not the observer), so the obvious alternative — keep draining the pipe withio.Copy(io.Discard, pr)untilpwcloses — would block forever and leak the goroutine. Absorbing failures at the writer boundary works regardless of whetherClose()runs, and removes the spurious push failure entirely (so there's no longer an unclassified error forexecuteBatchedto mishandle).Tests
TestPackStreamObserverScannerErrorDoesNotAbortUploadfeeds non-pack bytes (Scanner fails parsing the header mid-stream) and asserts every byte still comes back out ofReadwith no error, whileScannerError()records the failure.🤖 Generated with Claude Code
Note
Low Risk
Localized change to bootstrap pack streaming with a clear contract and regression test; no auth or data-model changes.
Overview
Fixes pack uploads failing when the side-channel
packfile.Scannerstops early (malformed pack or parse error). The observer tee used to write directly to the pipe; whenconsumeclosed the reader,io.TeeReadersurfacedio.ErrClosedPipefromReadand killed the push despite the documented rule that scanner failures are non-fatal for the upload.The tee now writes through a
bestEffortWriterthat records the first write failure, drops later observer bytes, and always reports a successful write so the upload stream keeps flowing. Failures remain visible viaScannerError()for debugging.Adds
TestPackStreamObserverScannerErrorDoesNotAbortUpload, which streams non-pack garbage, expects a full byte-for-byteReadAllwith no error, and asserts a scanner error was stored.Reviewed by Cursor Bugbot for commit f6bc49f. Configure here.