{"record":{"id":"623d177d7966938c","repo":"VictoriaMetrics/VictoriaMetrics","slug":"wrong-data-size-uploaded-to-q-got-d-bytes-want","errorCode":null,"errorMessage":"wrong data size uploaded to %q; got %d bytes; want %d bytes","messagePattern":"wrong data size uploaded to %q; got (.+?) bytes; want (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/backup/fsremote/fsremote.go","lineNumber":183,"sourceCode":"\t}\n\tw, err := os.Create(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot create file %q: %w\", path, err)\n\t}\n\tn, err := io.Copy(w, r)\n\tif err := w.Sync(); err != nil {\n\t\treturn fmt.Errorf(\"cannot fsync file: %q: %w\", w.Name(), err)\n\t}\n\tif err1 := w.Close(); err1 != nil && err == nil {\n\t\terr = err1\n\t}\n\tif err != nil {\n\t\t_ = os.RemoveAll(path)\n\t\treturn fmt.Errorf(\"cannot upload data to %q: %w\", path, err)\n\t}\n\tif uint64(n) != p.Size {\n\t\t_ = os.RemoveAll(path)\n\t\treturn fmt.Errorf(\"wrong data size uploaded to %q; got %d bytes; want %d bytes\", path, n, p.Size)\n\t}\n\treturn nil\n}\n\nfunc (fs *FS) mkdirAll(filePath string) error {\n\tdir := filepath.Dir(filePath)\n\tif err := os.MkdirAll(dir, 0700); err != nil {\n\t\treturn fmt.Errorf(\"cannot create directory %q: %w\", dir, err)\n\t}\n\treturn nil\n}\n\nfunc (fs *FS) path(p common.Part) string {\n\treturn filepath.Join(p.LocalPath(fs.Dir), fmt.Sprintf(\"%016X_%016X_%016X\", p.FileSize, p.Offset, p.Size))\n}\n\n// DeleteFile deletes filePath at fs.\n//","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/backup/fsremote/fsremote.go#L165-L201","documentation":"After a successful copy/sync/close, UploadPart compares the number of bytes written (io.Copy's return) with p.Size from the part metadata. A mismatch means the reader produced fewer (or more) bytes than the part metadata promised. The partially-uploaded file is removed and this error is returned so a corrupt part never remains on the remote.","triggerScenarios":"Calling UploadPart with a reader whose data length doesn't match p.Size — the part filename encodes Size as %016X, so this fires when the source snapshot changed size after the part list was computed, the wrong reader/offset was passed, or a compressing/limiting reader returned short reads.","commonSituations":"Database files modified during backup (snapshot taken without proper locking / hardlink snapshot skipped); passing a size-limited reader with the wrong limit; metadata computed from an earlier backup run reused with new data; reading through a flaky pipe that returns EOF early.","solutions":["Re-snapshot the source data so file sizes are stable, recompute parts, then re-upload","Verify the reader passed to UploadPart covers exactly p.Size bytes at p.Offset (use io.LimitReader or pread with the correct offsets)","Re-run the upload with fresh part metadata — the mismatched file was already removed","Never mutate source files during backup; use the snapshot mechanism the tool provides"],"exampleFix":"// before: reading the whole file instead of the exact part window\nf, _ := os.Open(srcPath)\nerr := fsRemote.UploadPart(part, f) // size mismatch: whole file != part.Size\n// after: bound the reader to the part's size at its offset\nf, _ := os.Open(srcPath)\nif _, err := f.Seek(int64(part.Offset), io.SeekStart); err != nil { return err }\nerr = fsRemote.UploadPart(part, io.LimitReader(f, int64(part.Size)))","handlingStrategy":"validation","validationCode":"import \"os\"\nfunc partReader(r io.Reader, p Part) (io.Reader, error) {\n\tf, ok := r.(*os.File)\n\tif !ok { return nil, fmt.Errorf(\"need *os.File to seek to part offset\") }\n\tif _, err := f.Seek(int64(p.Offset), io.SeekStart); err != nil { return nil, err }\n\treturn io.LimitReader(f, int64(p.Size)), nil\n}","typeGuard":null,"tryCatchPattern":"err := fsRemote.UploadPart(part, r)\nif err != nil && strings.Contains(err.Error(), \"wrong data size uploaded\") {\n\t// reader produced != part.Size bytes: recompute parts from a fresh snapshot and retry\n}","preventionTips":["Always bound the reader to exactly part.Size bytes (io.LimitReader after seeking to Offset)","Compute part metadata and readers from the same immutable snapshot","Never reuse part lists from a previous backup run against changed data","Cross-check source file sizes against part.FileSize before uploading"],"tags":["backup","size-mismatch","upload","validation"],"backgroundTag":"data-size-mismatch","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}