Stop Writer.Resume from finishing an unfinished large file whose parts do not match the new content
I maintainer di solito rispondono entro 1 giorno
@ffumero2003 ci sta già lavorando.
Dal 28/10/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Context
With Writer.Resume = true, the writer picks an unfinished large file by name alone and finishes it with every part B2 already holds. It compares SHA-1s only for parts the new stream reaches. Parts beyond the end of the new content are never checked and stay in the part list sent to b2_finish_large_file, so the stored object is the earlier, longer content while Close returns nil. When several unfinished uploads share the name, the last one listed wins. When a mismatch is detected, there is no way to cancel and restart other than by hand.
Stale content type and file info on resume are tracked in Backblaze/blazer#156 and are not part of this issue.
Current behavior
At a5e0d13:
- b2/writer.go:419-428: selection by exact name; last match wins. The listing is not prefix-scoped on the server: base/base.go:1595-1600 (
ListUnfinishedLargeFiles) sends no prefix, so every unfinished file in the bucket is paged through. - b2/writer.go:443-467: every listed part goes into
seen; base/base.go:1456-1468 (CompileParts) and :1563-1592 (FinishLargeFile) send all ofseenaspartSha1Array. - b2/writer.go:201-212: the only content check, per chunk the new stream produces.
- b2/writer.go:436-441:
checkResumedLockandcheckResumedEncryptioncompare Object Lock and encryption settings (including the SSE-C key ID added in merged Backblaze/blazer#153), not the part count or size. - b2/writer.go:201-204: the mismatch path returns without
cnk.buf.Close(), leaving a temp file inFileBufferDirwithUseFileBuffer.
Reproduced locally with a recording test server: an unfinished file with five 4-byte parts (aaaa to eeee), resumed with ChunkSize = 4 and 12 bytes aaaabbbbcccc. Close returned nil, no part was uploaded, and the finish request carried five part hashes. With two unfinished files of the same name listed, the writer finished the last one.
Expected behavior
Resume either finishes exactly the new content, or returns an error.
Acceptance criteria
- R1. Resuming with content shorter than the unfinished upload returns an error (or restarts in the opt-in mode) and never finishes with extra parts.
- R2. Two unfinished uploads with the same name give a deterministic, documented outcome.
- R3. The mismatch path removes the file-buffer temp file.
In scope
Proposed change
In getLargeFile (b2/writer.go):
- List with the name as server-side prefix and, when more than one unfinished file matches, refuse or choose deterministically (newest first) and document it.
- At
Close, refuse to finish unless the part list is exactly1..nfor the new content. - Add an opt-in mode that cancels a mismatched unfinished file and starts a new one.
- Close the chunk buffer on the mismatch path.
Behavior without Resume does not change.
Out of scope
- Stale content type and file info on resume, tracked in #156.
- Changes to behavior without
Resume.
Verification
Run the repository regression checks with live credentials unset:
unset B2_APPLICATION_KEY_ID B2_APPLICATION_KEY B2_ACCOUNT_ID B2_ACCOUNT_KEY
go build ./...
go vet ./...
go test -race -count=1 ./b2/... ./base
- Reproduce the supplied five-part unfinished upload resumed with only three parts, and the multiple unfinished-file selection case.
- Assert no finish publishes extra parts, the selected outcome is deterministic/documented, and the mismatch path removes the file-buffer temp file; show match controls still pass.
- Expected result: the checks above succeed and the observable outcomes in Acceptance criteria are demonstrated. If a check cannot run, report
Could not run because: ...; if it starts but fails, reportCould not complete because: .... A skipped check is not a pass.
Links
Backblaze/blazer#156 (stale content type or file info on resume). Merged Backblaze/blazer#153 added SSE-C checks to the same resume path. Backblaze/blazer#157 (resume in the sync engine) would rely on this path.
- Lingua principale
- Go
- Stelle
- 66
- Fork
- 18
- Merge medio
- 1g 10h
- PR unite (30g)
- 132
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Backblaze/blazer
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
Bucket.Attrs never returns ReplicationConfig: replication configuration is write-onlyForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
test: skip the fuzz non-vacuity guard when replaying a single seedForse già presa @ffumero2003 l’ha presa 5 giorni fa. Apertatesting
Backblaze/blazer#330 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Backblaze/blazer
Issue simili
-
needs-triage typo
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
llm-d-incubation/llm-d-scaling-manager#122 ·
I maintainer di solito rispondono entro 1 giorno
-
good first issue severity: low tech-debt
Difficoltà 2/5 Mezza giornata Idoneità per principianti 75/100
TMHSDigital/subenum#329 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] Backend summarize min() / max() panics when a field has no numeric valuesForse già presa @weng5e l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
grafana/grafana-infinity-datasource#1832 ·
I maintainer di solito rispondono entro 1 giorno
-
tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
GillMacedo/godebugdiff#13 ·