gofr-dev/gofr · error

response retrieved is nil

Error message

response retrieved is nil 

What it means

ErrNilResponse is the sentinel error of the GoFr S3 file datasource reported when a GetObject call succeeds at the HTTP level but the returned response body is nil, so there is no data stream to read from. It is wrapped by Read as '%w: S3 file is empty', meaning the S3 object could not be materialized into a readable body. This is a defensive check against SDK/proxy anomalies rather than a normal user error.

Source

Thrown at pkg/gofr/datasource/file/s3/file.go:40

//nolint:revive // s3.S3File is repetitive. A better name could have been chosen, but it's too late as it's already exported.
type S3File struct {
	conn         s3Client
	name         string
	offset       int64
	logger       Logger
	metrics      Metrics
	size         int64
	contentType  string
	body         io.ReadCloser
	lastModified time.Time
}

func (*S3File) Sys() any {
	return nil
}

var (
	ErrNilResponse = errors.New("response retrieved is nil ")
	// ErrRangeNotHonored is returned when a byte-range read was requested but the
	// backend answered with the whole object (no Content-Range header). Filling the
	// caller's buffer from byte 0 in that case would silently serve the wrong bytes,
	// so the read is refused instead.
	ErrRangeNotHonored = errors.New("s3 backend did not honor the requested byte range")
)

// Close closes the response body returned in Open/Create methods if the response body is not nil.
func (f *S3File) Close() error {
	bucketName := getBucketName(f.name)

	defer f.sendOperationStats(&FileLog{
		Operation: "CLOSE",
		Location:  getLocation(bucketName)}, time.Now())

	if f.body != nil {
		return f.body.Close()
	}

View on GitHub (pinned to 187eb24962)

Solutions

  1. Check that the target S3-compatible backend actually returns a body stream for GetObject (curl/S3 console or aws s3 cp the object to confirm it is retrievable).
  2. Upgrade github.com/aws/aws-sdk-go-v2 and the gofr module to latest versions to rule out SDK field-contract changes.
  3. If using a mock S3 client, populate GetObjectOutput.Body (e.g. io.NopCloser(bytes.NewReader(data))) instead of returning an empty struct.
  4. Handle the error with errors.Is(err, s3.ErrNilResponse) and treat it as a failed/retryable read rather than nil-data.

Example fix

// before: mock returns empty output
res := &s3.GetObjectOutput{}
// after
res := &s3.GetObjectOutput{Body: io.NopCloser(bytes.NewReader(objBytes))}
Defensive patterns

Strategy: try-catch

Validate before calling

// no pre-call validation possible; ensure backend/mocks supply a Body
// when stubbing:
// out := &s3.GetObjectOutput{Body: io.NopCloser(bytes.NewReader(data))}

Try / catch

n, err := f.Read(buf)
if err != nil {
    if errors.Is(err, s3datasource.ErrNilResponse) {
        // backend returned no body: fail fast or retry once
    }
    return err
}

Prevention

When it happens

Trigger: Calling (*S3File).Read when the underlying s3.GetObjectOutput has a nil Body — e.g. an S3-compatible backend (MinIO, mock, or misbehaving proxy) returns a 200 with no body stream, or a test/mock client returns an output struct without Body.

Common situations: Pointing the datasource at non-AWS S3-compatible stores that don't fully honor the GetObject contract; using fake/mocked AWS clients in tests that forget Body; SDK version mismatches where output struct fields change.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/6909484b0056d0d6. Report an issue: GitHub.