juicedata/juicefs · warning
failed to get object with the end out of range, expect "o",
Error message
failed to get object with the end out of range, expect "o", but got %q, error: %s
What it means
Emitted by the 'get partial object' case of `juicefs objbench` when a read whose requested range extends past the end of the object (offset 4, size 2 on a 5-byte object) does not return just the remaining byte "o". Unlike the other partial-get checks this is wrapped in `warning()`, so it is reported as a warning rather than a hard failure: per the S3 spec, ranges exceeding object length should be truncated, but some backends legitimately return an error. It flags backends that neither truncate the range nor (if erroring) behave as the benchmark expects.
Source
Thrown at cmd/objbench.go:833
// get first
if d, e := get(blob, key, 0, 1); e != nil || d != "h" {
return fmt.Errorf(`failed to get the first byte:, expect "h", but got %q, error: %s`, d, e)
}
// get last
if d, e := get(blob, key, 4, 1); e != nil || d != "o" {
return fmt.Errorf(`failed to get the last byte: expect "o", but got %q, error: %s`, d, e)
}
// get last 3
if d, e := get(blob, key, 2, 3); e != nil || d != "llo" {
return fmt.Errorf(`failed to get the last three bytes: expect "llo", but got %q, error: %s`, d, e)
}
// get middle
if d, e := get(blob, key, 2, 2); e != nil || d != "ll" {
return fmt.Errorf(`failed to get two bytes: expect "ll", but got %q, error: %s`, d, e)
}
// get the end out of range
if d, e := get(blob, key, 4, 2); e != nil || d != "o" {
return warning(fmt.Errorf(`failed to get object with the end out of range, expect "o", but got %q, error: %s`, d, e))
}
// get the off out of range
if d, e := get(blob, key, 6, 2); e != nil || d != "" {
return warning(fmt.Errorf(`failed to get object with the offset out of range, expect "", but got %q, error: %s`, d, e))
}
return nil
})
runCase("head an object", 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 h, err := blob.Head(ctx, key); err != nil {
return fmt.Errorf("failed to head object %s", err)
} else {
if h.Key() != key {View on GitHub (pinned to c9a67b23e8)
Solutions
- Determine which behavior the backend has: truncation (correct per S3) or 416 (tolerable, warning-level).
- If the backend returns 416 for over-range reads, treat this warning as expected or adjust the storage layer to clamp ranges to object size.
- If bytes are wrong/garbled, fix the tail-range slicing in the ObjectStorage implementation.
- Check the appended %s error to distinguish an HTTP status problem from a data problem.
Example fix
// before (strict bounds -> 416)
if off+limit > size { return nil, ErrOutOfRange }
// after (clamp to object size, S3 semantics)
if limit < 0 || off+limit > size { limit = size - off } Defensive patterns
Strategy: fallback
Validate before calling
// clamp ranges to object size before calling Get:
h, _ := blob.Head(ctx, key)
size := h.Size
if off >= size { /* skip or expect empty */ }
if limit > 0 && off+limit > size { limit = size - off } Try / catch
d, e := get(blob, key, 4, 2)
if e != nil || d != "o" {
// tolerate 416/InvalidRange backends, but log for review
log.Printf("out-of-range read: got=%q err=%v", d, e)
// fallback: Head for size, then re-read clamped range
} Prevention
- Implement S3 range semantics (truncate over-long ranges) in custom stores.
- Treat this as a warning-level check; document backends that return 416 instead.
- Head the object to get its size and clamp client-side ranges before Get.
When it happens
Trigger: ObjectStorage.Get(key, off=4, size=2) against a 5-byte object: returns wrong bytes, the full tail plus padding, or errors (e.g. HTTP 416 InvalidRange) instead of returning the truncated "o".
Common situations: S3-compatible endpoints that return 416 for overlong ranges instead of clamping; NAS/HDFS-backed stores with strict bounds checks; custom implementations with different out-of-range semantics; benchmarking a new backend to document its range behavior.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- failed to get the first byte:, expect "h", but got %q, error
- failed to get the last byte: expect "o", but got %q, error:
- failed to get the last three bytes: expect "llo", but got %q
- failed to get two bytes: expect "ll", but got %q, error: %s
- ErrNotSUP
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/a12cd4af1a9e2eac.
Report an issue: GitHub.