Skip to content

Fix S3 response body resource leak — use defer Close() #7

Description

@ngoyal16

Problem

In main.go lines 105–109, the S3 object body is closed manually but not with defer:

bodyBytes, err := io.ReadAll(getObjectOutput.Body)
getObjectOutput.Body.Close()
if err != nil {
    return fmt.Errorf("failed to read S3 object body: %w", err)
}

If io.ReadAll returns an error, Close() is still called. However, the pattern is fragile:

  1. If any code is added between GetObject and io.ReadAll that could panic or return early, the body would leak.
  2. The Close() error is ignored — a failed close could indicate incomplete reads or connection issues.
  3. This doesn't follow the idiomatic Go pattern of defer body.Close() immediately after acquisition.

Proposed Solution

Use defer immediately after acquiring the body:

getObjectOutput, err := s3Client.GetObject(ctx, &s3.GetObjectInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
})
if err != nil {
    return fmt.Errorf("failed to fetch object %s/%s: %w", bucket, key, err)
}
defer getObjectOutput.Body.Close()

bodyBytes, err := io.ReadAll(getObjectOutput.Body)
if err != nil {
    return fmt.Errorf("failed to read S3 object body: %w", err)
}

Acceptance Criteria

  • All io.ReadCloser bodies from S3 are closed via defer
  • No resource leaks under error or panic conditions
  • Existing tests (if any) still pass

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtech-debtCode quality, refactoring, and technical debt

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions