{"record":{"id":"0427b675655e7437","repo":"juicedata/juicefs","slug":"failed-to-get-two-bytes-expect-ll-but-got-q","errorCode":null,"errorMessage":"failed to get two bytes: expect \"ll\", but got %q, error: %s","messagePattern":"failed to get two bytes: expect \"ll\", but got %q, error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/objbench.go","lineNumber":829,"sourceCode":"\t\t\treturn fmt.Errorf(\"put object failed: %s\", err)\n\t\t}\n\t\tdefer blob.Delete(ctx, key) //nolint:errcheck\n\n\t\t// get first\n\t\tif d, e := get(blob, key, 0, 1); e != nil || d != \"h\" {\n\t\t\treturn fmt.Errorf(`failed to get the first byte:, expect \"h\", but got %q, error: %s`, d, e)\n\t\t}\n\t\t// get last\n\t\tif d, e := get(blob, key, 4, 1); e != nil || d != \"o\" {\n\t\t\treturn fmt.Errorf(`failed to get the last byte: expect \"o\", but got %q, error: %s`, d, e)\n\t\t}\n\t\t// get last 3\n\t\tif d, e := get(blob, key, 2, 3); e != nil || d != \"llo\" {\n\t\t\treturn fmt.Errorf(`failed to get the last three bytes: expect \"llo\", but got %q, error: %s`, d, e)\n\t\t}\n\t\t// get middle\n\t\tif d, e := get(blob, key, 2, 2); e != nil || d != \"ll\" {\n\t\t\treturn fmt.Errorf(`failed to get two bytes: expect \"ll\", but got %q, error: %s`, d, e)\n\t\t}\n\t\t// get the end out of range\n\t\tif d, e := get(blob, key, 4, 2); e != nil || d != \"o\" {\n\t\t\treturn warning(fmt.Errorf(`failed to get object with the end out of range, expect \"o\", but got %q, error: %s`, d, e))\n\t\t}\n\t\t// get the off out of range\n\t\tif d, e := get(blob, key, 6, 2); e != nil || d != \"\" {\n\t\t\treturn warning(fmt.Errorf(`failed to get object with the offset out of range, expect \"\", but got %q, error: %s`, d, e))\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"head an object\", func(blob object.ObjectStorage) error {\n\t\tbr := []byte(\"hello\")\n\t\tif err := blob.Put(ctx, key, bytes.NewReader(br)); err != nil {\n\t\t\treturn fmt.Errorf(\"put object failed: %s\", err)\n\t\t}\n\t\tdefer blob.Delete(ctx, key) //nolint:errcheck","sourceCodeStart":811,"sourceCodeEnd":847,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/objbench.go#L811-L847","documentation":"Emitted by the 'get partial object' case of `juicefs objbench` when a middle ranged read (offset 2, size 2) of the \"hello\" object does not return exactly \"ll\". This checks interior (not touching either edge) partial reads. Failures indicate the backend returned extra, missing, or shifted bytes, or the Get call errored.","triggerScenarios":"ObjectStorage.Get(key, off=2, size=2) returns more than 2 bytes (e.g. \"llo\" or the whole object), fewer bytes, misaligned bytes, or a non-nil error.","commonSituations":"Custom ObjectStorage that ignores `limit` and reads to EOF; proxies buffering the full object; range translation bugs in S3-compatible endpoints; double-counted offsets after prior failed reads.","solutions":["Check the embedded %s error for the storage-level cause.","Confirm the backend honors limited reads (`--range bytes=2-3`).","Fix the limit handling in the custom Get implementation so exactly `size` bytes are returned.","Run objbench's get cases in isolation to confirm the fix."],"exampleFix":"// before (limit ignored)\nr, err := s.get(key, off, -1)\n// after\nr, err := s.get(key, off, limit)","handlingStrategy":"validation","validationCode":"rc, err := blob.Get(ctx, key, 2, 2)\nif err != nil { return err }\nbuf, _ := io.ReadAll(rc); rc.Close()\nif len(buf) != 2 { return fmt.Errorf(\"expected 2 bytes, got %d\", len(buf)) }","typeGuard":null,"tryCatchPattern":"d, e := get(blob, key, 2, 2)\nif e != nil || d != \"ll\" {\n    log.Printf(\"interior range read failed: got=%q err=%v\", d, e)\n}","preventionTips":["Assert the returned byte count matches the requested limit in tests.","Make sure Get implementations always cap output at `limit` bytes.","Benchmark new backends with objbench before wiring them into JuiceFS."],"tags":["object-storage","range-read","benchmark"],"backgroundTag":"unexpected-response-shape","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}