juicedata/juicefs · error
Length mismatch: %v != %v
Error message
Length mismatch: %v != %v
What it means
wSlice.Finish(length) is the finalization call on a staging slice writer; it validates that the final size the caller declares equals the length tracked on the slice (s.length, i.e. what was actually written via Write/FlushTo). If they differ, the library refuses to finalize because committing would record a size inconsistent with the data written, and returns "Length mismatch: <tracked> != <given>".
Source
Thrown at pkg/chunk/cached_store.go:487
panic(fmt.Sprintf("Invalid offset: %d < %d", offset, s.uploaded))
}
for i, block := range s.pages {
start := i * s.store.conf.BlockSize
end := start + s.store.conf.BlockSize
if start >= s.uploaded && end <= offset {
if block != nil {
s.upload(i)
}
s.uploaded = end
}
}
return nil
}
func (s *wSlice) Finish(length int) error {
if s.length != length {
return fmt.Errorf("Length mismatch: %v != %v", s.length, length)
}
n := (length-1)/s.store.conf.BlockSize + 1
if err := s.FlushTo(n * s.store.conf.BlockSize); err != nil {
return err
}
for i := 0; i < s.pendings; i++ {
if err := <-s.errors; err != nil {
s.uploadError = err
return err
}
}
return nil
}
func (s *wSlice) Abort() {
for i := range s.pages {
for _, b := range s.pages[i] {View on GitHub (pinned to c9a67b23e8)
Solutions
- Pass the actual number of bytes written to Finish — track the return value of Write calls instead of assuming a size.
- Check for earlier swallowed write errors; a short write before Finish means the tracked length is legitimately smaller.
- If the intended size is known up front, write exactly that many bytes (or pad/truncate) before calling Finish.
- Audit the calling code path for a stale variable holding an old length after the content changed.
Example fix
// before
n := computeExpectedSize(path)
err := w.Finish(n) // assumes size
// after
written := 0
for _, chunk := range chunks {
k, e := w.Write(chunk)
if e != nil { return e }
written += k
}
err := w.Finish(written) Defensive patterns
Strategy: validation
Validate before calling
if trackedBytes != declaredLength {
return fmt.Errorf("refusing Finish: wrote %d bytes but Finish(%d) requested", trackedBytes, declaredLength)
}
err := w.Finish(declaredLength) Try / catch
if err != nil && strings.HasPrefix(err.Error(), "Length mismatch:") {
parts := strings.Split(err.Error(), " ")
tracked, _ := strconv.Atoi(parts[2])
return w.Finish(tracked) // finalize with the actual written size
} Prevention
- Always derive the Finish argument from the cumulative Write return values, never from an assumed size.
- Check every Write error before finalizing; partial writes change the tracked length.
- When a fixed size is required, write exactly that many bytes (pad or truncate) first.
- Add an assertion in wrappers that compares bytes-written to the expected size before Finish.
When it happens
Trigger: Calling Finish(n) on a wSlice whose writes produced a different byte count than n — e.g. a caller that pre-computed the file size but wrote fewer/more bytes, or that calls Finish after a partial Write failed silently.
Common situations: Applications that write via the JuiceFS SDK/fs layer and pass a stale or assumed size to Finish; a truncated or failed write earlier in the pipeline so tracked length is short; off-by-one or unit mistakes (bytes vs. records) when computing the final length.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/16c583b426c41485.
Report an issue: GitHub.