hashicorp/terraform · error
failed to upload state: %w
Error message
failed to upload state: %w
What it means
Thrown in RemoteClient.put() (s3/client.go:240) when the S3 manager Uploader fails to PutObject the state file during a write. The wrapped (%w) error is the raw AWS SDK error. This aborts the state write; because the MD5 digest is written afterward, a failed upload means no digest row is created either.
Source
Thrown at internal/backend/remote-state/s3/client.go:240
input.SSECustomerAlgorithm = aws.String(string(s3EncryptionAlgorithm))
input.SSECustomerKeyMD5 = aws.String(c.getSSECustomerKeyMD5())
} else {
input.ServerSideEncryption = s3EncryptionAlgorithm
}
}
if c.acl != "" {
input.ACL = s3types.ObjectCannedACL(c.acl)
}
log.Info("Uploading remote state")
uploader := manager.NewUploader(c.s3Client, func(u *manager.Uploader) {
u.ClientOptions = optFns
})
_, err := uploader.Upload(ctx, input)
if err != nil {
return fmt.Errorf("failed to upload state: %w", err)
}
if err := c.putMD5(ctx, sum[:]); err != nil {
// if this errors out, we unfortunately have to error out altogether,
// since the next Get will inevitably fail.
return fmt.Errorf("failed to store state MD5: %w", err)
}
return nil
}
func (c *RemoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
ctx := context.TODO()
log := c.logger(operationClientDelete)
ctx, baselog := baselogging.NewHcLogger(ctx, log)
ctx = baselogging.RegisterLogger(ctx, baselog)View on GitHub (pinned to c9def3e214)
Solutions
- Grant s3:PutObject on the state key (and kms:Encrypt/GenerateDataKey for SSE-KMS).
- Verify the kms_key_id exists, is enabled, and is in the same region as the bucket.
- Check for Object Lock / bucket policy denying the overwrite.
- Retry on SlowDown/throttling with backoff.
Example fix
// before: role can read but not write state
// after
// {
// "Effect": "Allow",
// "Action": ["s3:PutObject"],
// "Resource": "arn:aws:s3:::mycorp-tfstate/*"
// } Defensive patterns
Strategy: try-catch
Validate before calling
// Probe write (and KMS) access before the apply writes state
// _, err := s3Client.PutObject(ctx, &s3.PutObjectInput{Bucket:&bucket, Key:aws.String("tf-probe"), Body: bytes.NewReader([]byte("{}"))})
// if err != nil { /* grant s3:PutObject / kms:Encrypt */ } Type guard
// React by AWS error code on the wrapped upload error
// var apiErr smithy.APIError
// if errors.As(err, &apiErr) {
// switch apiErr.ErrorCode() {
// case "AccessDenied": /* s3:PutObject / kms:Encrypt */
// case "SlowDown": /* retry */
// }
// } Try / catch
// Retry throttling, surface permission errors
// var apiErr smithy.APIError
// if errors.As(err, &apiErr) && apiErr.ErrorCode()=="SlowDown" { /* backoff retry */ } else { return err } Prevention
- Grant s3:PutObject on the state key and kms:Encrypt/GenerateDataKey for SSE-KMS.
- Verify kms_key_id is valid, enabled, and same-region.
- Check Object Lock / bucket policy won't block overwrites.
When it happens
Trigger: s3:PutObject denied; SSE-KMS key id invalid/unreachable or kms:Encrypt missing; bucket policy or Object Lock (WORM) blocking the write; S3 throttling; bucket in a different region than the client; wrong ACL string.
Common situations: Least-privilege role missing s3:PutObject; KMS key id typo or key disabled; Object Lock retention preventing overwrite; cross-account bucket without proper bucket-policy + KMS grants; ACL set to an unsupported value.
Related errors
- Unable to list objects in S3 bucket %q with prefix %q: %w
- Unable to access object %q in S3 bucket %q: %w
- failed to unlock both S3 and DynamoDB: S3 error: %v, DynamoD
- failed to unlock S3: %v
- unable to retrieve file from S3 bucket '%s' with key '%s': %
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/97df555c594cbdb6.
Report an issue: GitHub.