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

  1. Grant oss:DeleteObject to the configured credentials on the bucket/state prefix.
  2. Verify the object exists; if it was already deleted, the workspace delete can be considered partially complete.
  3. Confirm the endpoint region matches the bucket region.
  4. 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

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


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)