hashicorp/terraform · error
failed to upload state
Error message
failed to upload state %s: %#v
What it means
Thrown by RemoteClient.Put when bucket.PutObject(c.stateFile, body, options...) fails. The actual OSS PutObject API call returned an error — ACL/SSE/content-length options were applied but the upload was rejected.
Solutions
- Grant oss:PutObject on the bucket/object to the configured credentials.
- Verify bucket name and endpoint region match.
- Check the object key prefix (stateFile) is valid and writable.
- If using serverSideEncryption or acl, confirm the bucket allows the requested SSE/ACL.
- Retry on transient network errors; inspect the %#v underlying error for the SDK error code.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: confirm PutObject permission via a head/conditional probe (lightweight). // At minimum, validate the bucket is reachable and writable in staging.
Try / catch
// Inspect the underlying OSS service error code to decide retry vs surface.
if err := bucket.PutObject(c.stateFile, body, options...); err != nil {
var se oss.ServiceError
if errors.As(err, &se) && isRetryableCode(se.Code) { /* backoff + retry */ }
return fmt.Errorf("failed to upload state %s: %#v", c.stateFile, err)
} Prevention
- Grant oss:PutObject on the state prefix in the deployer RAM policy.
- Keep bucket region and endpoint consistent.
- Verify SSE/ACL options are permitted by the bucket policy.
When it happens
Trigger: PutObject returns non-nil: bucket does not exist, credentials lack oss:PutObject permission, bucket is read-only or in a locked-down policy, object key (stateFile path) is invalid, or network/endpoint failure.
Common situations: Wrong region endpoint causing bucket-not-found; RAM policy missing oss:PutObject; SSE-AES256 requested but bucket has conflicting encryption config; ACL option conflicts with bucket policy; large state hitting size limits.
Related errors
- error deleting state
- error describing table store
- error getting bucket
- error getting bucket: %#v
- failed to upload state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/81443eb705c794b3.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/oss/client.go:121
if err != nil {
return diags.Append(fmt.Errorf("error getting bucket: %#v", err))
}
body := bytes.NewReader(data)
var options []oss.Option
if c.acl != "" {
options = append(options, oss.ACL(oss.ACLType(c.acl)))
}
options = append(options, oss.ContentType("application/json"))
if c.serverSideEncryption {
options = append(options, oss.ServerSideEncryption("AES256"))
}
options = append(options, oss.ContentLength(int64(len(data))))
if body != nil {
if err := bucket.PutObject(c.stateFile, body, options...); err != nil {
return diags.Append(fmt.Errorf("failed to upload state %s: %#v", c.stateFile, err))
}
}
sum := md5.Sum(data)
if err := c.putMD5(sum[:]); err != nil {
// if this errors out, we unfortunately have to error out altogether,
// since the next Get will inevitably fail.
return diags.Append(fmt.Errorf("failed to store state MD5: %s", err))
}
return diags
}
func (c *RemoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
bucket, err := c.ossClient.Bucket(c.bucketName)
if err != nil {
return diags.Append(fmt.Errorf("error getting bucket %s: %#v", c.bucketName, err))
}View on GitHub (pinned to d32a084675)