hashicorp/terraform · error
failed to create tag
Error message
failed to create tag: %s -> %s: %s
What it means
Returned by CreateTag() when the Tencent Cloud Tag service (tag v20180813) rejects the CreateTag call. The COS backend uses a Tencent tag on the bucket to implement distributed state locking; creating that lock tag failed. The key, value, and the underlying API error are included.
Solutions
- Inspect the wrapped API error string for the Tencent error code (e.g. ResourceInUse for duplicate, AuthFailure for perms).
- Grant `tag:CreateTag` (and `tag:DeleteTag`, `tag:DescribeTags`) to the principal in CAM.
- If the tag already exists from a stale lock, run `terraform force-unlock <ID>` or delete the `tencentcloud-terraform-lock` tag manually, then retry.
- For quota errors, remove unused tags or request a quota increase.
Example fix
// before: principal lacks tag permissions, lock acquisition fails
// after: attach CAM policy granting the Tag actions
{
"version":"2.0",
"statement":[{"effect":"allow","action":["tag:CreateTag","tag:DeleteTag","tag:DescribeTags"],"resource":"*"}]
} Defensive patterns
Strategy: validation
Validate before calling
// Before locking, confirm Tag service permissions
func canCreateLockTag(ctx context.Context, tagClient *tag.Client, key, value string) error {
req := tag.NewCreateTagRequest()
k, v := key+".probe", value
req.TagKey, req.TagValue = &k, &v
_, err := tagClient.CreateTag(req)
if err != nil {
if strings.Contains(err.Error(), "Unauthorized") || strings.Contains(err.Error(), "AuthFailure") {
return fmt.Errorf("principal lacks tag:CreateTag: %w", err)
}
return err
}
// clean up probe
del := tag.NewDeleteTagRequest(); del.TagKey, del.TagValue = &k, &v
tagClient.DeleteTag(del)
return nil
} Type guard
func isTagPermissionError(err error) bool {
s := err.Error()
return strings.Contains(s, "AuthFailure") || strings.Contains(s, "UnauthorizedOperation")
}
func isTagDuplicate(err error) bool { return strings.Contains(err.Error(), "ResourceInUse") || strings.Contains(err.Error(), "already exist") } Try / catch
// Duplicate-tag and permission errors are not retryable; only transient 5xx is
if isTagDuplicate(err) { return backoff.Permanent(fmt.Errorf("stale lock tag exists; force-unlock: %w", err)) }
if isTagPermissionError(err) { return backoff.Permanent(fmt.Errorf("grant tag:CreateTag: %w", err)) } Prevention
- Grant `tag:CreateTag`, `tag:DeleteTag`, `tag:DescribeTags` to the COS backend principal.
- Always release locks through Terraform; do not manually remove the lock tag mid-run.
- After a crashed apply, force-unlock before the next run to clear stale lock tags.
- Monitor tag quota usage for the account/region.
When it happens
Trigger: c.tagClient.CreateTag(request) returns a non-nil error. Causes: missing/denied `tag:CreateTag` permission, the tag key/value pair already exists (duplicate), tag quota exceeded for the account/region, or a transient Tag API failure.
Common situations: Sub-account used for the COS backend lacks Tag service permissions; the lock tag from a crashed previous run already exists; the account hit the Tencent Cloud tag-key/value quota; the Tag service endpoint region mismatch.
Related errors
- failed to delete tag
- bucket not exists
- failed to empty bucket
- lock file not exists
- failed to create bucket
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/70daa666867a5b53.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/cos/client.go:431
tagKey := response.Response.Tags[0].TagKey
tagValue := response.Response.Tags[0].TagValue
exists = key == *tagKey && value == *tagValue
return
}
// CreateTag create tag by key and value
func (c *remoteClient) CreateTag(key, value string) error {
request := tag.NewCreateTagRequest()
request.TagKey = &key
request.TagValue = &value
_, 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 nilView on GitHub (pinned to d32a084675)