hashicorp/terraform · error

failed to delete tag: %s -> %s: %s

Error message

failed to delete tag: %s -> %s: %s

What it means

Raised by DeleteTag() when the Tencent Cloud Tag service's DeleteTag API returns an error. DeleteTag is called during Unlock() (via cosUnlock) to release the state lock; failure means the lock tag could not be removed, leaving the state potentially locked. cosUnlock retries up to 30 times with 1s sleeps before surfacing the error.

Source

Thrown at internal/backend/remote-state/cos/client.go:446

	_, err := c.tagClient.CreateTag(request)
	log.Printf("[DEBUG] create tag %s:%s: error: %v", key, value, err)
	if err != nil {
		return fmt.Errorf("failed to create tag: %s -> %s: %s", key, value, err)
	}

	return nil
}

// DeleteTag create tag by key and value
func (c *remoteClient) DeleteTag(key, value string) error {
	request := tag.NewDeleteTagRequest()
	request.TagKey = &key
	request.TagValue = &value

	_, err := c.tagClient.DeleteTag(request)
	log.Printf("[DEBUG] delete tag %s:%s: error: %v", key, value, err)
	if err != nil {
		return fmt.Errorf("failed to delete tag: %s -> %s: %s", key, value, err)
	}

	return nil
}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Grant the credentials tag:DeleteTag (or QcloudTAGFullAccess) and re-attempt the unlock.
  2. If the unlock already partially succeeded, manually check the Tag console for the 'tencentcloud-terraform-lock' tag and remove it if stale.
  3. Re-authenticate with fresh credentials/STS and retry 'terraform force-unlock <lock-id>'.
  4. If 5xx, wait for Tag service recovery and retry.

Example fix

# grant tag:DeleteTag, then force-unlock
terraform force-unlock <lock-id>
# or remove the stale tag value under key 'tencentcloud-terraform-lock' in the Tag console
Defensive patterns

Strategy: retry

Validate before calling

// Verify tag:DeleteTag permission before relying on auto-unlock.
func canDeleteTag(ctx context.Context, t *tag.Client) error {
    // best-effort: DescribeTags works but Create/Delete need QcloudTAGFullAccess
    return nil
}

Try / catch

if err := c.Unlock(check); err != nil {
    // tag delete failed after 30 retries: grant tag:DeleteTag, or 'terraform force-unlock' + manual tag removal
}

Prevention

When it happens

Trigger: At client.go:443-446: c.tagClient.DeleteTag(request) returns err after the 30-iteration retry loop in cosUnlock exhausts. Occurs when tag permissions are insufficient, the tag does not exist, STS expired, or the Tag API is unavailable over the whole retry window.

Common situations: Sub-account credentials with COS rights but not Tag:DeleteTag rights; STS token expired during a long apply; tag was already deleted by a concurrent unlock; Tag API regional outage lasting >30s.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/8281b15772d42721. Report an issue: GitHub.