hashicorp/terraform · error

failed to access object

Error message

failed to access object '%s' in bucket '%s': %w

What it means

HeadObject returned a non-nil error that is not a 404 ServiceError, so the backend surfaces a wrapped generic access error. This is the metadata-fetch step of getObject; only 404 is treated as 'state not found, initialize'. Any other failure (auth, 403, 412, 5xx, transport, SSE-C mismatch) lands here.

Solutions

  1. If using SSE-C, confirm `sse_customer_key`, `sse_customer_key_sha256`, and `sse_customer_algorithm` match the key used to write the object.
  2. Verify the IAM principal has OBJECT_READ/OBJECT_INSPECT on the bucket and that namespace/bucket names are correct.
  3. For transient 5xx, retry — getDefaultRetryPolicy already retries idempotent reads but custom transport or non-retryable codes may bypass it.
  4. Check OCI service health for the objectstorage service in the region.

Example fix

// before: misconfigured SSE-C (key rotated, sha256 stale)
terraform {
  backend "oci" {
    bucket               = "tf-state"
    namespace            = "idxx"
    key                  = "prod.tfstate"
    sse_customer_key     = var.key     // rotated
    sse_customer_key_sha256 = var.old_sha // stale -> 303
  }
}
// after: regenerate sha256 from the same key and pass both
terraform {
  backend "oci" {
    bucket               = "tf-state"
    namespace            = "idxx"
    key                  = "prod.tfstate"
    sse_customer_key     = var.key
    sse_customer_key_sha256 = filesha256("sse.key") // matches
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate SSE-C config symmetry before any read
func validateSSEC(c *RemoteClient) error {
    hasKey := c.SSECustomerKey != ""
    hasSha := c.SSECustomerKeySHA256 != ""
    if hasKey != hasSha {
        return fmt.Errorf("SSE-C requires both sse_customer_key and sse_customer_key_sha256")
    }
    return nil
}

Type guard

func isServiceError(err error) (common.ServiceError, bool) {
    var se common.ServiceError
    return se, errors.As(err, &se)
}

Try / catch

if _, err := c.objectStorageClient.HeadObject(ctx, headRequest); err != nil {
    var se common.ServiceError
    if errors.As(err, &se) {
        switch se.GetHTTPStatusCode() {
        case 403: // fix IAM/SSE-C
        case 404: // treat as not-found
        }
    }
    // non-OCI transport error -> retry/backoff
}

Prevention

When it happens

Trigger: Wrong SSE-C customer key/sha256 supplied (403/412 on a customer-encrypted object); IAM policy missing OBJECT_READ on the bucket; wrong namespace or bucket name; transient OCI 5xx; bucket deleted or in a different region.

Common situations: SSE-C key rotated and backend config not updated; instance principal missing the dynamic group/role; wrong `namespace` in backend config (namespace is tenancy-specific, not region); bucket renamed.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/023ed4c28180cf48. Report an issue: GitHub.

Appendix: 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 OCI

View on GitHub (pinned to d32a084675)