gofr-dev/gofr · error
%w: negative offset %d
Error message
%w: negative offset %d
What it means
ReadAt wraps ErrOutOfRange with the offending value when given a negative offset, because a byte position below zero can never be valid in S3 (object keys are byte-addressed from 0). The request is rejected locally before any network call is made, so it fails fast and cheaply.
Source
Thrown at pkg/gofr/datasource/file/s3/file.go:207
func (f *S3File) ReadAt(p []byte, offset int64) (n int, err error) {
bucketName := getBucketName(f.name)
fileName := f.relativeKey()
var msg string
st := statusErr
defer f.sendOperationStats(&FileLog{
Operation: "READAT",
Location: getLocation(bucketName),
Status: &st,
Message: &msg,
}, time.Now())
// A negative offset is never valid. Reject it before spending a request.
if offset < 0 {
msg = fmt.Sprintf("Negative offset %v", offset)
return 0, fmt.Errorf("%w: negative offset %d", ErrOutOfRange, offset)
}
// An empty destination reads nothing; return without a request.
if len(p) == 0 {
st = statusSuccess
return 0, nil
}
// A read that starts at or past EOF has nothing to return. Guard here so it
// costs no request and, importantly, so io.ReaderAt callers see io.EOF rather
// than an unsatisfiable Range (bytes=<size>-...) turning into an HTTP 416.
// A read that merely straddles EOF (offset < size <= offset+len(p)) is valid:
// S3 returns the available bytes and io.ReadFull below surfaces the short fill
// as io.EOF along with the real count, honoring the io.ReaderAt contract.
if offset >= f.size {
st = statusSuccess
return 0, io.EOF
}View on GitHub (pinned to 187eb24962)
Solutions
- Validate the offset before calling: if offset < 0 { return/adjust }.
- Fix offset computation so it cannot go negative (clamp to 0 or use unsigned/checked math).
- Use Seek/Read for relative positioning instead of negative ReadAt offsets.
- Handle errors.Is(err, s3.ErrOutOfRange) to distinguish caller bugs from I/O errors.
Example fix
// before
n, err := f.ReadAt(buf, -1)
// after
if offset < 0 { return fmt.Errorf("invalid offset %d", offset) }
n, err := f.ReadAt(buf, offset) Defensive patterns
Strategy: validation
Validate before calling
func safeReadAt(f *s3datasource.S3File, p []byte, off int64) (int, error) {
if off < 0 {
return 0, fmt.Errorf("offset must be >= 0, got %d", off)
}
return f.ReadAt(p, off)
} Type guard
func validOffset(off int64) bool { return off >= 0 } Prevention
- Validate offsets at API boundaries before calling ReadAt.
- Clamp computed offsets: if off < 0 { off = 0 }.
- Never use -1 as a sentinel with ReadAt (unlike some OS APIs).
- Use checked/unsigned math for offset arithmetic.
When it happens
Trigger: Calling (*S3File).ReadAt(p []byte, offset) with offset < 0 — e.g. a computed offset that underflowed, or passing -1 as a 'don't care' sentinel as some APIs allow.
Common situations: Integer arithmetic bugs producing negative positions (size subtraction going negative); porting code from APIs where -1 means 'read from current position'; unvalidated user-supplied offsets.
Related errors
- out of range
- incorrect file type
- response retrieved is nil
- s3 backend did not honor the requested byte range
- %w: S3 file is empty
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/ac1369e6291c271b.
Report an issue: GitHub.