AWS S3
HeadObject error
400 Bad Request
file upload error
client error handling

A client error 400 occurred when calling the HeadObject operation Bad Request Completed 1 parts with ... files remaining

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A 400 Bad Request from S3 during HeadObject usually means the request shape is wrong, not that the network failed. When that message appears alongside multipart-upload progress such as "Completed 1 parts with ... files remaining," the upload tool has often reached a metadata check or resume check and failed there rather than during the raw part transfer itself.

What HeadObject Is Used For

HeadObject asks S3 for object metadata without downloading the object body. SDKs and CLI tools use it for tasks such as:

  • checking whether an object already exists
  • reading size or ETag
  • validating state before or after an upload
  • resuming or verifying multipart transfer behavior

A direct boto3 call looks like this:

python
1import boto3
2from botocore.exceptions import ClientError
3
4s3 = boto3.client("s3", region_name="ca-central-1")
5
6try:
7    response = s3.head_object(Bucket="my-bucket", Key="uploads/report.csv")
8    print(response["ContentLength"])
9except ClientError as error:
10    print(error.response["Error"]["Code"])
11    print(error.response["Error"]["Message"])

If S3 rejects the bucket name, key, region, signing details, or required headers, the request can fail before any useful metadata is returned.

Why This Shows Up in Multipart Upload Flows

Higher-level upload tools do more than stream bytes. They often perform extra lookups before or after transferring parts. That is why a message about completed parts can appear right next to a HeadObject failure.

The important interpretation is:

  • the part transfer progress text is not necessarily the failing step
  • the failing step may be a metadata lookup surrounding the upload

That distinction matters because otherwise people debug bandwidth and retry settings when the real problem is an invalid HeadObject request.

Check Bucket, Key, and Region First

The fastest way to reduce the problem is to log the exact request inputs and compare them with the actual S3 object location.

python
1bucket = "my-bucket"
2key = "uploads/report.csv"
3region = "ca-central-1"
4
5print(bucket)
6print(key)
7print(region)

Then test the same lookup with the AWS CLI:

bash
aws s3api head-object --bucket my-bucket --key uploads/report.csv --region ca-central-1

This removes some application logic from the picture. If the CLI call fails the same way, the issue is likely in the request details themselves.

S3 keys are exact strings. They are not filesystem paths with normalization rules. Trailing spaces, doubled separators, case differences, and encoding mistakes all matter.

Do Not Ignore Signing and Header Requirements

Some HeadObject calls fail because the request is missing something required for that object. A few examples:

  • wrong bucket region causing signature mismatch
  • missing headers for objects encrypted with SSE-C
  • malformed bucket or key values
  • a custom endpoint or acceleration setting that does not match the bucket setup

That is why a generic 400 can still come from a very specific request-construction bug.

If your application generates the object key dynamically, keep that logic boring and deterministic:

python
1from pathlib import Path
2
3local_file = Path("reports") / "2026-03.csv"
4key = f"uploads/{local_file.name}"
5print(key)

Simple key generation avoids a surprising number of S3 lookup failures.

Permissions Can Also Affect Verification Steps

An upload workflow may succeed in sending parts and still fail on metadata validation if the IAM identity lacks the permission needed for the follow-up read or head request.

So verify that the principal has the permissions required for the whole workflow, not only for the upload operation itself.

Common Pitfalls

  • Assuming the multipart progress line identifies the failing step.
  • Using the wrong region and debugging everything except request signing.
  • Building object keys with accidental whitespace, wrong case, or doubled separators.
  • Treating S3 keys like local paths that can be normalized automatically.
  • Checking upload permissions but forgetting that metadata lookups may need additional access too.

Summary

  • 'HeadObject is a metadata lookup, and a 400 Bad Request usually points to malformed request details.'
  • Multipart progress text can be incidental if the real failure happens in a surrounding verification call.
  • Verify bucket, key, region, and headers with one direct head-object request.
  • Keep S3 key generation simple and exact.
  • Debug the request shape first before assuming the multipart upload mechanism itself is broken.

Course illustration
Course illustration

All Rights Reserved.