{"record":{"id":"81443eb705c794b3","repo":"hashicorp/terraform","slug":"failed-to-upload-state-s-v","errorCode":null,"errorMessage":"failed to upload state %s: %#v","messagePattern":"failed to upload state (.+?): %#v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/oss/client.go","lineNumber":121,"sourceCode":"\tif err != nil {\n\t\treturn diags.Append(fmt.Errorf(\"error getting bucket: %#v\", err))\n\t}\n\n\tbody := bytes.NewReader(data)\n\n\tvar options []oss.Option\n\tif c.acl != \"\" {\n\t\toptions = append(options, oss.ACL(oss.ACLType(c.acl)))\n\t}\n\toptions = append(options, oss.ContentType(\"application/json\"))\n\tif c.serverSideEncryption {\n\t\toptions = append(options, oss.ServerSideEncryption(\"AES256\"))\n\t}\n\toptions = append(options, oss.ContentLength(int64(len(data))))\n\n\tif body != nil {\n\t\tif err := bucket.PutObject(c.stateFile, body, options...); err != nil {\n\t\t\treturn diags.Append(fmt.Errorf(\"failed to upload state %s: %#v\", c.stateFile, err))\n\t\t}\n\t}\n\n\tsum := md5.Sum(data)\n\tif err := c.putMD5(sum[:]); err != nil {\n\t\t// if this errors out, we unfortunately have to error out altogether,\n\t\t// since the next Get will inevitably fail.\n\t\treturn diags.Append(fmt.Errorf(\"failed to store state MD5: %s\", err))\n\t}\n\treturn diags\n}\n\nfunc (c *RemoteClient) Delete() tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\tbucket, err := c.ossClient.Bucket(c.bucketName)\n\tif err != nil {\n\t\treturn diags.Append(fmt.Errorf(\"error getting bucket %s: %#v\", c.bucketName, err))\n\t}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/oss/client.go#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm PutObject permission via a head/conditional probe (lightweight).\n// At minimum, validate the bucket is reachable and writable in staging.","typeGuard":null,"tryCatchPattern":"// Inspect the underlying OSS service error code to decide retry vs surface.\nif err := bucket.PutObject(c.stateFile, body, options...); err != nil {\n    var se oss.ServiceError\n    if errors.As(err, &se) && isRetryableCode(se.Code) { /* backoff + retry */ }\n    return fmt.Errorf(\"failed to upload state %s: %#v\", c.stateFile, err)\n}","preventionTips":["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."],"tags":["alibaba-cloud","oss","putobject","iam","remote-state","upload"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}