juicedata/juicefs · error
first key should be test, but got %s
Error message
first key should be test, but got %s
What it means
Raised in the objbench 'list objects' filesystem case: the second listed entry must be the test object under `key` ('test'), but a different key was returned. The message text says 'first key' but actually checks objs[1] — the key that objbench just Put. This validates that the list returns the newly written object in the expected position.
Source
Thrown at cmd/objbench.go:902
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 {
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))
}View on GitHub (pinned to c9a67b23e8)
Solutions
- Remove leftover files/keys from the test directory/prefix and rerun.
- Check how the backend normalizes keys in List vs Put (trailing/leading slashes).
- Verify ordering matches the reference file:// implementation.
- Clear any entry caches on filesystem-backed stores before rerunning.
- Upgrade/align JuiceFS versions if backend and CLI differ.
Example fix
// before: backend returns key "/test" for put key "test"
return &entry{key: "/" + rel, ...}
// after: keep keys consistent with Put
return &entry{key: rel, ...} Defensive patterns
Strategy: validation
Validate before calling
// ensure the test key exists and prefix is clean before listing
objs, _ := listAll(ctx, blob, "", "", 10)
keys := make([]string, 0, len(objs))
for _, o := range objs { keys = append(keys, o.Key()) }
// expect keys == ["", key] Try / catch
if objs[1].Key() != key {
log.Printf("got %q, want %q; check key normalization and leftovers", objs[1].Key(), key)
} Prevention
- Use unique keys/prefixes per run to avoid leftovers.
- Normalize keys (no leading slashes) consistently.
- Match ordering behavior of the reference file backend.
- Clean the benchmark directory before runs.
When it happens
Trigger: listAll(ctx, blob, "", "", 2) returned 2 entries whose first is "" but whose second entry's Key() != key — caused by leftover objects in the test prefix, incorrect ordering, or the backend returning a differently-normalized key (e.g. leading slash).
Common situations: Dirty test directory containing other files that shift entry positions; backend key normalization adding/removing separators; backend sorting that misplaces the new object; stale caches in a custom implementation.
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
- list should return 2 keys, but got %d
- first key should be empty string, but got %s
- first object size should be 0, but got %d
- size of first key shold be 5, but got %v
- list failed: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/955aa2f6ef5df021.
Report an issue: GitHub.