juicedata/juicefs · error
size of first key shold be 5, but got %v
Error message
size of first key shold be 5, but got %v
What it means
Raised in the objbench 'list objects' filesystem case: the second listed entry is the just-uploaded 5-byte object 'test', so its Size() must be 5, but the backend reported a different size. This asserts that listing returns accurate object sizes (typo 'shold' is in the source message).
Source
Thrown at cmd/objbench.go:905
}
defer blob.Delete(ctx, key) //nolint:errcheck
if isFileSystem {
objs, err := listAll(ctx, blob, "", "", 2)
if err == nil {
if len(objs) != 2 {
return fmt.Errorf("list should return 2 keys, but got %d", len(objs))
}
if objs[0].Key() != "" {
return fmt.Errorf("first key should be empty string, but got %s", objs[0].Key())
}
if objs[0].Size() != 0 {
return fmt.Errorf("first object size should be 0, but got %d", objs[0].Size())
}
if objs[1].Key() != key {
return fmt.Errorf("first key should be test, but got %s", objs[1].Key())
}
if objs[1].Size() != 5 {
return fmt.Errorf("size of first key shold be 5, but got %v", objs[1].Size())
}
now := time.Now()
if objs[1].Mtime().Before(now.Add(-30*time.Second)) || objs[1].Mtime().After(now.Add(time.Second*30)) {
return fmt.Errorf("mtime of key should be within 30 seconds, but got %s", objs[1].Mtime().Sub(now))
}
} else {
return fmt.Errorf("list failed: %s", err)
}
objs, err = listAll(ctx, blob, "", "test2", 1)
if err != nil {
return fmt.Errorf("list failed: %s", err)
} else if len(objs) != 0 {
return fmt.Errorf("list should not return anything, but got %d", len(objs))
}
} else {
objs, err2 := listAll(ctx, blob, "", "", 1)
if err2 == nil {View on GitHub (pinned to c9a67b23e8)
Solutions
- Fix the backend's List to populate Size() from the file/object's actual length (5 for "hello").
- Verify Put is fully flushed before List runs (no async write-behind reporting wrong sizes).
- Compare with the reference file:// implementation in pkg/object.
- Clear size/attr caches on the filesystem-backed store.
- Rerun objbench to confirm.
Example fix
// before
return &entry{key: name, size: 0}, nil // size never populated
// after
fi, _ := os.Stat(path)
return &entry{key: name, size: fi.Size()}, nil Defensive patterns
Strategy: type-guard
Validate before calling
objs, _ := listAll(ctx, blob, "", "", 2)
if len(objs) > 1 && objs[1].Key() == key && objs[1].Size() != 5 {
log.Printf("reported size %d, want 5", objs[1].Size())
} Type guard
func sizeMatches(o object.Object, want uint64) bool {
return o.Size() == want
} Try / catch
if s := objs[1].Size(); s != 5 {
log.Printf("list size %d != put size 5; check flush/caching", s)
} Prevention
- Populate Size() from actual object length in List.
- Ensure Put completes (flush) before listing.
- Avoid caching stale sizes in custom backends.
- Validate with objbench after any List changes.
When it happens
Trigger: After Put of []byte("hello"), listAll returns the key correctly but objs[1].Size() != 5 — e.g. the backend reports the directory stat size, a block-aligned size, 0, or a stale cached size.
Common situations: Custom file backend using os.Stat's Size() on a directory or returning allocated size; a backend whose List fills size from a stale cache; backends that don't populate size in list results at all; uploads still in flight/flushed asynchronously.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- first object size should be 0, but got %d
- list should return 2 keys, but got %d
- first key should be empty string, but got %s
- first key should be test, but got %s
- list failed: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/41631a7a5325ece6.
Report an issue: GitHub.