juicedata/juicefs · error
Cannot overwrite uploaded block: %d < %d
Error message
Cannot overwrite uploaded block: %d < %d
What it means
After part of a wSlice has been uploaded (s.uploaded marks the boundary), earlier bytes are considered immutable. WriteAt rejects any write whose offset is below the uploaded boundary to preserve consistency between staged data and already-persisted blocks. This prevents silently rewriting data that object storage already received.
Source
Thrown at pkg/chunk/cached_store.go:260
writeback: store.conf.Writeback,
tierID: tierID,
}
}
func (s *wSlice) SetID(id uint64) {
s.id = id
}
func (s *wSlice) SetWriteback(enabled bool) {
s.writeback = enabled
}
func (s *wSlice) WriteAt(p []byte, off int64) (n int, err error) {
if int(off)+len(p) > chunkSize {
return 0, fmt.Errorf("write out of chunk boundary: %d > %d", int(off)+len(p), chunkSize)
}
if off < int64(s.uploaded) {
return 0, fmt.Errorf("Cannot overwrite uploaded block: %d < %d", off, s.uploaded)
}
// Fill previous blocks with zeros
if s.length < int(off) {
zeros := make([]byte, int(off)-s.length)
_, _ = s.WriteAt(zeros, int64(s.length))
}
for n < len(p) {
indx := s.index(int(off) + n)
boff := (int(off) + n) % s.store.conf.BlockSize
var bs = pageSize
if indx > 0 || bs > s.store.conf.BlockSize {
bs = s.store.conf.BlockSize
}
bi := boff / bs
bo := boff % bs
var page *PageView on GitHub (pinned to c9a67b23e8)
Solutions
- Only append beyond s.uploaded; compute write offsets relative to the current uploaded boundary.
- Do not reuse a wSlice to rewrite uploaded regions — create a new slice/chunk for corrected data.
- Check caller's offset bookkeeping (writeback/append position) to ensure it never goes backwards.
- If triggered by retries, make retry logic idempotent by skipping writes below the uploaded boundary instead of reissuing them.
Example fix
// before
slice.WriteAt(data, oldOff) // oldOff < slice.uploaded
// after
if int64(oldOff) < int64(slice.uploaded) {
return fmt.Errorf("region already uploaded, skipping rewrite at %d", oldOff)
}
slice.WriteAt(data, oldOff) Defensive patterns
Strategy: validation
Validate before calling
if int64(off) < int64(slice.uploaded) {
return errors.New("cannot write below uploaded boundary; use an append offset")
} Try / catch
n, err := slice.WriteAt(p, off)
if err != nil && strings.Contains(err.Error(), "Cannot overwrite uploaded block") {
// advance offset or allocate a new slice; never retry same offsets
} Prevention
- Track append position from the slice's uploaded boundary
- Make retries idempotent — skip writes already covered by upload
When it happens
Trigger: Calling wSlice.WriteAt with an off smaller than s.uploaded — e.g. re-writing an already-flushed prefix of the slice, a retry that re-issues an old write, or an offset-tracking bug where the caller's file position lags the uploaded boundary.
Common situations: Random-write workloads revisiting earlier regions of an append-only staging file; crash recovery or writeback replays reapplying stale writes; misordered internal upload/write pipelines in custom data paths.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- writeend %s: %s
- write out of chunk boundary: %d > %d
- RangerPermissionChecker for volume: " + volName + " is alrea
- RangerPermissionChecker for volume: " + volName + " is alrea
- ErrFuncTimeout
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/e7777236c0eb7ef5.
Report an issue: GitHub.