gofr-dev/gofr · error
%w: S3 file is empty
Error message
%w: S3 file is empty
What it means
This error wraps ErrNilResponse: during (*S3File).Read, the GetObject call succeeded but the response body was nil, so the S3 file appears empty/unreadable and the read is aborted with 0 bytes. The wrapper message names the wrapped sentinel, so errors.Is(err, s3.ErrNilResponse) matches it.
Source
Thrown at pkg/gofr/datasource/file/s3/file.go:153
// empty objects and backends that reject "bytes=0-" behave as before.
if f.offset > 0 {
input.Range = aws.String(fmt.Sprintf("bytes=%d-", f.offset))
}
res, err := f.conn.GetObject(context.TODO(), input)
if err != nil {
msg = fmt.Sprintf("Failed to retrieve %q: %v", fileName, err)
return 0, err
}
// Close the body from any previous read before replacing it, otherwise the
// earlier HTTP connection leaks.
f.closeBody()
f.body = res.Body
if f.body == nil {
msg = fmt.Sprintf("File %q is nil", fileName)
return 0, fmt.Errorf("%w: S3 file is empty", ErrNilResponse)
}
// If a byte range was requested (offset > 0) but the backend replied with the
// whole object (no Content-Range), io.ReadFull would fill p from byte 0 and
// silently serve the wrong bytes. Refuse rather than corrupt the read.
if f.offset > 0 && res.ContentRange == nil {
f.closeBody()
f.body = nil
msg = fmt.Sprintf("Range request for %q not honored by backend", fileName)
return 0, ErrRangeNotHonored
}
// normalizeReadFull fills p completely unless the object ends first, reporting
// a short fill as io.EOF along with the real byte count — honoring the io.Reader
// contract that n reflects the number of bytes actually read.
n, err = normalizeReadFull(f.body, p)
if err != nil && !errors.Is(err, io.EOF) {View on GitHub (pinned to 187eb24962)
Solutions
- Confirm the object is fully retrievable with the AWS CLI and that the bucket/key are correct.
- Fix or upgrade the S3-compatible backend/proxy so GetObject always streams a body on 200.
- Populate Body in any mock/test client used with this datasource.
- Check errors.Is(err, s3.ErrNilResponse) in your error handling and retry or fail the read explicitly.
Example fix
// handling
if err != nil {
if errors.Is(err, s3datasource.ErrNilResponse) {
// backend returned no body; retry or surface a 5xx
}
} Defensive patterns
Strategy: try-catch
Try / catch
n, err := f.Read(buf)
if err != nil && errors.Is(err, s3datasource.ErrNilResponse) {
// treat as failed read; retry or surface backend health issue
return fmt.Errorf("read %s: %w", name, err)
} Prevention
- Health-check the object store at startup.
- Avoid stub clients that omit Body.
- Monitor for degraded 200 responses from proxies.
- Pin and update SDK versions together with gofr.
When it happens
Trigger: Any Read() call on an S3File where the backend returns a GetObjectOutput with a nil Body — malformed backend responses, incomplete mocks, or SDK/backend contract mismatches.
Common situations: S3-compatible stores (MinIO/SeaweedFS) returning degraded 200 responses; test stubs of GetObjectOutput without Body; intermittent proxy failures stripping the body.
Related errors
- response retrieved is nil
- errFileNotOpenForReading
- s3 backend did not honor the requested byte range
- %w: negative offset %d
- out of range
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/2ca74360c2db2385.
Report an issue: GitHub.