hashicorp/terraform · error
failed to access object '%s' in bucket '%s': %w
Error message
failed to access object '%s' in bucket '%s': %w
What it means
Raised in RemoteClient.getObject when the OCI HeadObject call fails with an error that is NOT a 404 (the 404 branch treats a missing state file as a normal initialization and returns an empty payload). It wraps the raw SDK error along with the configured object path and bucket name so the practitioner can see which state file could not be inspected. Any HeadObject failure other than NotNotFound surfaces here: auth, authorization, throttling, server faults, network, or a wrong namespace/bucket.
Source
Thrown at internal/backend/remote-state/oci/client.go:74
BucketName: common.String(c.bucketName),
RequestMetadata: common.RequestMetadata{
RetryPolicy: getDefaultRetryPolicy(),
},
}
if c.SSECustomerKey != "" && c.SSECustomerKeySHA256 != "" {
headRequest.OpcSseCustomerKey = common.String(c.SSECustomerKey)
headRequest.OpcSseCustomerKeySha256 = common.String(c.SSECustomerKeySHA256)
headRequest.OpcSseCustomerAlgorithm = common.String(c.SSECustomerAlgorithm)
}
// Get object from OCI
headResponse, headErr := c.objectStorageClient.HeadObject(ctx, headRequest)
if headErr != nil {
var ociHeadErr common.ServiceError
if errors.As(headErr, &ociHeadErr) && ociHeadErr.GetHTTPStatusCode() == 404 {
logger.Debug(" State file '%s' not found. Initializing Terraform state...", c.path)
return &remote.Payload{}, nil
} else {
return nil, fmt.Errorf("failed to access object '%s' in bucket '%s': %w", c.path, c.bucketName, headErr)
}
}
getRequest := objectstorage.GetObjectRequest{
NamespaceName: common.String(c.namespace),
ObjectName: common.String(c.path),
BucketName: common.String(c.bucketName),
IfMatch: headResponse.ETag,
RequestMetadata: common.RequestMetadata{
RetryPolicy: getDefaultRetryPolicy(),
},
}
if c.SSECustomerKey != "" && c.SSECustomerKeySHA256 != "" {
getRequest.OpcSseCustomerKey = common.String(c.SSECustomerKey)
getRequest.OpcSseCustomerKeySha256 = common.String(c.SSECustomerKeySHA256)
getRequest.OpcSseCustomerAlgorithm = common.String(c.SSECustomerAlgorithm)
}
// Get object from OCIView on GitHub (pinned to c9def3e214)
Solutions
- Verify the backend 'bucket', 'namespace', and 'key'/'prefix' values match an existing bucket and object path using 'oci os object head --bucket-name <b> --namespace <ns> --name <key>'.
- Confirm the IAM principal Terraform runs as has OBJECT_INSPECT + OBJECT_READ on the bucket and OBJECT_CREATE/OBJECT_OVERWRITE for writes (check the policy and any dynamic group).
- Re-authenticate or refresh credentials: run 'oci session refresh' (or re-export OCI_AUTH/OCI_SESSION_TOKEN) when using instance/principal delegation token auth that has expired.
- If intermittent, rely on the SDK retry policy (getDefaultRetryPolicy) and re-run 'terraform init'/'terraform plan'; for sustained 429s request a service-limit increase.
- Enable OCI request logging and confirm the resolved region/tenancy; a wrong region yields authorization-style failures even with valid credentials.
Example fix
# before (wrong namespace)
terraform {
backend "oci" {
namespace = "idexample" # typo
bucket = "tf-state"
key = "prod/terraform.tfstate"
}
}
# after (correct namespace from 'oci os ns get')
terraform {
backend "oci" {
namespace = "idxxxxxxxxxxx"
bucket = "tf-state"
key = "prod/terraform.tfstate"
}
} Defensive patterns
Strategy: retry
Validate before calling
// Before init/plan, confirm head reachability and permissions with the OCI CLI:
// oci os bucket get --namespace <ns> --name <bucket>
// oci os object head --namespace <ns> --bucket-name <bucket> --name <key>
// In Go, validate config before constructing the backend:
if c.namespace == "" || c.bucketName == "" || c.path == "" {
return fmt.Errorf("oci backend requires namespace, bucket and key to be set")
} Type guard
// Distinguish 404 (legitimate empty init) from other head failures:
var ociErr common.ServiceError
if errors.As(err, &ociErr) && ociErr.GetHTTPStatusCode() == 404 {
// object missing -> initialize fresh state
} Try / catch
resp, err := c.objectStorageClient.HeadObject(ctx, headRequest)
if err != nil {
var se common.ServiceError
if errors.As(err, &se) && se.GetHTTPStatusCode() == 404 {
return &remote.Payload{}, nil // expected: first run
}
return nil, fmt.Errorf("failed to access object '%s' in bucket '%s': %w", c.path, c.bucketName, err)
} Prevention
- Pin and verify namespace/bucket/key in the backend block before running Terraform.
- Grant the IAM principal OBJECT_INSPECT + OBJECT_READ on the state bucket.
- Keep credentials fresh (instance principal delegation token / session token) to avoid auth failures at head time.
- Use the default retry policy for transient head failures.
When it happens
Trigger: A HeadObject request to objectstorage.ObjectStorageClient.HeadObject (client.go:67) returns a non-nil error that either is not a common.ServiceError or is a ServiceError whose HTTP status is not 404 (e.g. 401 NotAuthenticated, 404 on the bucket/namespace rather than the object, 403 NotAuthorizedOrNotFound, 429 TooManyRequests, 500/503).
Common situations: Wrong namespace or bucket name in the backend config; the IAM user lacks OBJECT_READ / READ on the bucket; OCID/region mismatch in the provider config; expired session token; OCI throttling the control plane; transient 5xx or network blip between Terraform and the object storage endpoint.
Related errors
- failed to upload object: %w
- unable to read 'content' from response: %w
- failed to read existing lock file content: %w
- error creating multipart upload: %s
- failed to access object HttpStatusCode: %d OpcRequestId: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/023ed4c28180cf48.
Report an issue: GitHub.