hashicorp/terraform · error
error deleting state
Error message
error deleting state %s: %#v
What it means
Thrown by RemoteClient.Delete when bucket.DeleteObject(c.stateFile) fails. The OSS DeleteObject API call returned an error while removing the state object for a workspace being deleted.
Solutions
- Grant oss:DeleteObject to the configured credentials on the bucket/state prefix.
- Verify the object exists; if it was already deleted, the workspace delete can be considered partially complete.
- Confirm the endpoint region matches the bucket region.
- Retry on transient network errors; inspect the %#v SDK error code.
Defensive patterns
Strategy: try-catch
Try / catch
// Treat 'NoSuchKey' as already-deleted and succeed; otherwise surface.
if err := bucket.DeleteObject(c.stateFile); err != nil {
var se oss.ServiceError
if errors.As(err, &se) && se.Code == "NoSuchKey" { /* idempotent success */ } else {
return diags.Append(fmt.Errorf("error deleting state %s: %#v", c.stateFile, err))
}
} Prevention
- Grant oss:DeleteObject on the state prefix.
- Make workspace deletion idempotent in automation (tolerate already-deleted objects).
- Confirm endpoint region before delete.
When it happens
Trigger: DeleteObject returns non-nil: credentials lack oss:DeleteObject, the object does not exist (depending on bucket versioning), the bucket is in a region/endpoint mismatch, or network failure.
Common situations: RAM policy missing oss:DeleteObject; object already removed manually; bucket versioning causing DeleteObject to behave differently; endpoint misconfiguration.
Related errors
- error getting bucket
- failed to upload state
- can't delete default state
- error describing table store
- error getting bucket: %#v
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a5c6461b2770eeaa.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/oss/client.go:144
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))
}
log.Printf("[DEBUG] Deleting remote state from OSS: %#v", c.stateFile)
if err := bucket.DeleteObject(c.stateFile); err != nil {
return diags.Append(fmt.Errorf("error deleting state %s: %#v", c.stateFile, err))
}
if err := c.deleteMD5(); err != nil {
log.Printf("[WARN] Error deleting state MD5: %s", err)
}
return diags
}
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
if c.otsTable == "" {
return "", nil
}
info.Path = c.lockPath()
if info.ID == "" {
lockID, err := uuid.GenerateUUID()
if err != nil {View on GitHub (pinned to d32a084675)