hashicorp/terraform · error
failed to upload state %s: %#v
Error message
failed to upload state %s: %#v
What it means
In RemoteClient.Put() (client.go:120-121), bucket.PutObject(stateFile, body, options...) failed uploading the state JSON to OSS. %#v surfaces the full OSS SDK error (code + request-id). This is the actual network/permissions write failure as opposed to the local Bucket() validation.
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 c9def3e214)
Solutions
- Read the %#v detail: NoSuchBucket -> recreate/fix bucket; AccessDenied -> grant oss:PutObject and check RAM role.
- Validate acl is one of private/public-read/public-read-write/default (oss.ACLType cast expects a canned value).
- If using a proxy, ensure HTTPS egress to the OSS endpoint is allowed.
- Re-run terraform apply; PutObject is safe to retry as it overwrites the key atomically.
Example fix
// before
backend "oss" {
bucket = "tf-state"
acl = "public" // invalid canned ACL
}
// after
backend "oss" {
bucket = "tf-state"
acl = "private"
} Defensive patterns
Strategy: retry
Validate before calling
// Validate acl/server_side_encryption values and credential scope before apply.
func validACL(a string) bool {
switch a {
case "", "private", "public-read", "public-read-write", "default":
return true
}
return false
} Try / catch
// Inspect the OSS error code in %#v; retry on transient 5xx/timeout,
// fail fast on AccessDenied/SignatureDoesNotMatch.
if oe, ok := err.(oss.ServiceError); ok {
switch oe.StatusCode {
case 500, 502, 503, 408:
return retry() // PutObject is idempotent overwrite
default:
return fail(oe)
}
} Prevention
- Use only valid OSS canned ACLs in the acl attribute.
- Ensure oss:PutObject is granted on the state prefix.
- Keep state files reasonably sized; very large states amplify timeout risk.
When it happens
Trigger: PutObject returns an error: NoSuchBucket, AccessDenied, RequestTimeout, SignatureDoesNotMatch, slow read/write timeout, or a transient 5xx from OSS. ACL, SSE, Content-Length options are attached so misconfig of acl/server_side_encryption can also trigger it.
Common situations: Bucket deleted after init; credentials rotated/expired; acl value not a valid OSS canned ACL; server_side_encryption=true against a bucket with conflicting KMS config; large state hitting body/timeout limits; network/proxy egress blocked to oss-*.aliyuncs.com.
Related errors
- error deleting state %s: %#v
- estimating object %s is exist got an error: %#v
- error getting bucket: %#v
- state data in OSS does not have the expected content. This
- error getting bucket: %#v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/81443eb705c794b3.
Report an issue: GitHub.