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

  1. Determine which behavior the backend has: truncation (correct per S3) or 416 (tolerable, warning-level).
  2. 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.
  3. If bytes are wrong/garbled, fix the tail-range slicing in the ObjectStorage implementation.
  4. 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

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/a12cd4af1a9e2eac. Report an issue: GitHub.