hashicorp/terraform · error
failed to upload object
Error message
failed to upload object: %w
What it means
PutObject (single-part state upload) failed; the error is wrapped verbatim. Common OCI causes: 403 (no OBJECT_CREATE/OBJECT_OVERWRITE), invalid or inaccessible KMS key, SSE-C customer key mismatch against the bucket's default encryption, quota exceeded, or 5xx.
Solutions
- Verify the principal has OBJECT_CREATE and (for overwrite) OBJECT_OVERWRITE on the bucket.
- If using KMS, confirm kms_key_id points to an active key in an accessible compartment and that the principal can use it (inspectKey, encrypt/decrypt).
- If using SSE-C, confirm key/sha256/algorithm are consistent across reads and writes.
- Retry transient 5xx; the existing retry policy handles idempotent PutObject failures.
Example fix
// before: backend uses a KMS key the runner principal cannot use
terraform {
backend "oci" { kms_key_id = "ocid1.key.oc1...old" }
}
// after: point at the active key the principal has encrypt/decrypt on
terraform {
backend "oci" { kms_key_id = var.active_kms_key_ocid }
} Defensive patterns
Strategy: retry
Validate before calling
// Verify write + KMS permissions before the first apply
func canWrite(c *RemoteClient) error {
probe := objectstorage.PutObjectRequest{
NamespaceName: common.String(c.namespace),
BucketName: common.String(c.bucketName),
ObjectName: common.String(c.path + ".probe"),
PutObjectBody: io.NopCloser(bytes.NewReader([]byte("probe"))),
}
if c.kmsKeyID != "" { probe.OpcSseKmsKeyId = common.String(c.kmsKeyID) }
_, err := c.objectStorageClient.PutObject(context.Background(), probe)
if err != nil { _ = c.objectStorageClient.DeleteObject(context.Background(), objectstorage.DeleteObjectRequest{NamespaceName: probe.NamespaceName, BucketName: probe.BucketName, ObjectName: probe.ObjectName}) }
return err
} Type guard
func isOCIError(err error) (common.ServiceError, bool) {
var se common.ServiceError
return se, errors.As(err, &se)
} Try / catch
// Retry transient 5xx/429 on PutObject; surface 4xx for config fixes
for i := 0; i < 3; i++ {
err := c.uploadSinglePartObject(ctx, data, sum)
if err == nil { break }
var se common.ServiceError
if errors.As(err, &se) && (se.GetHTTPStatusCode() == 429 || se.GetHTTPStatusCode() >= 500) {
time.Sleep(backoff(i)); continue
}
return err
} Prevention
- Grant the principal OBJECT_CREATE and OBJECT_OVERWRITE on the state bucket.
- Keep kms_key_id pointing at an active key the principal can use (encrypt/decrypt/inspectKey).
- Pin SSE-C keys as key+sha256 pairs in your secret manager.
- Watch for IAM/KMS changes that break the principal mid-pipeline.
When it happens
Trigger: IAM principal lacks OBJECT_CREATE/OBJECT_OVERWRITE; KMS key ID wrong, revoked, or in a different compartment the principal cannot use; SSE-C key rotated so writes now conflict with bucket default; object versioning/quota limits hit.
Common situations: Cross-team IAM change removed write permission; KMS key rotated but kms_key_id in backend config not updated; SSE-C and SSE-KMS both partially configured; bucket hard quota reached.
Related errors
- failed to access object
- error creating multipart upload
- failed to access object HttpStatusCode
- failed to get existing lock file
- failed to lock oci state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/5b01dcff16081db2.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/oci/client.go:195
RequestMetadata: common.RequestMetadata{
RetryPolicy: getDefaultRetryPolicy(),
},
}
// Handle encryption settings
if c.kmsKeyID != "" {
putRequest.OpcSseKmsKeyId = common.String(c.kmsKeyID)
} else if c.SSECustomerKey != "" && c.SSECustomerKeySHA256 != "" {
putRequest.OpcSseCustomerKey = common.String(c.SSECustomerKey)
putRequest.OpcSseCustomerKeySha256 = common.String(c.SSECustomerKeySHA256)
putRequest.OpcSseCustomerAlgorithm = common.String(c.SSECustomerAlgorithm)
}
logger.Info(fmt.Sprintf("Uploading remote state: %s", c.path))
putResponse, err := c.objectStorageClient.PutObject(ctx, putRequest)
if err != nil {
return fmt.Errorf("failed to upload object: %w", err)
}
logger.Info("Uploaded state file response: %+v\n", putResponse)
return nil
}
func (c *RemoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
return diags.Append(c.DeleteAllObjectVersions())
}
func (c *RemoteClient) DeleteAllObjectVersions() error {
request := objectstorage.ListObjectVersionsRequest{
BucketName: common.String(c.bucketName),
NamespaceName: common.String(c.namespace),
Prefix: common.String(c.path),
RequestMetadata: common.RequestMetadata{
RetryPolicy: getDefaultRetryPolicy(),View on GitHub (pinned to d32a084675)