juicedata/juicefs · error
list should return 2 keys, but got %d
Error message
list should return 2 keys, but got %d
What it means
Raised in the objbench 'list objects' case for filesystem-backed stores (isFileSystem): listAll(ctx, blob, "", "", 2) must return exactly 2 entries — the mandatory directory entry for "" (size 0) plus the test object "test" — but a different number of entries was returned. This verifies that filesystem-style backends emulate listing-with-directory-entries correctly.
Source
Thrown at cmd/objbench.go:893
runCase("delete non-exist", func(blob object.ObjectStorage) error {
if err := blob.Delete(ctx, key); err != nil {
return fmt.Errorf("deleting a non-existent object returns an error %v", err)
}
return nil
})
runCase("list objects", func(blob object.ObjectStorage) error {
br := []byte("hello")
if err := blob.Put(ctx, key, bytes.NewReader(br)); err != nil {
return fmt.Errorf("put object failed: %s", err)
}
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 {View on GitHub (pinned to c9a67b23e8)
Solutions
- Confirm the test directory/prefix is clean (no other keys beginning with the test prefix).
- If implementing a filesystem backend, ensure List returns the directory entry "" as the first object with size 0.
- Verify the backend honors the limit parameter the same way listAll accumulates pages.
- Check JuiceFS version — list semantics for file backends changed historically; upgrade to a consistent version.
- Rerun objbench on an empty temp directory to isolate.
Example fix
// before (custom fs backend list omits dir entry)
objs := []object.Object{fileObj}
// after
objs := []object.Object{&dirEntry{key: "", size: 0}, fileObj} // include "" entry first Defensive patterns
Strategy: type-guard
Validate before calling
objs, err := listAll(ctx, blob, "", "", 2)
if err == nil && len(objs) != 2 {
log.Printf("unexpected list length: %d", len(objs))
} Type guard
func hasDirEntry(objs []object.Object) bool {
return len(objs) > 0 && objs[0].Key() == "" && objs[0].Size() == 0
} Try / catch
objs, err := listAll(ctx, blob, "", "", 2)
if err != nil {
return err
}
if !hasDirEntry(objs) {
log.Printf("backend does not synthesize directory entry; not filesystem-conformant")
} Prevention
- Keep the benchmark directory clean of foreign keys.
- Implement List per the reference file:// backend including the "" entry.
- Respect the limit parameter when paging.
- Run objbench on an empty temp dir first.
When it happens
Trigger: The test puts one object at `key` under a filesystem backend (e.g. file:// or sftp://), then lists with prefix "" marker "" limit 2 and receives != 2 objects — typically because the backend does not synthesize the empty-string directory entry, or leftover objects in the test prefix change the count.
Common situations: Custom filesystem-like ObjectStorage implementations that omit the "" directory placeholder; running against a shared/dirty directory containing other files; a limit/offset handling bug in the backend's List method.
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 key should be empty string, but got %s
- first object size should be 0, but got %d
- first key should be test, but got %s
- size of first key shold be 5, but got %v
- Cannot get file system.
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/e614c262f68b38e0.
Report an issue: GitHub.