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

  1. Inspect the wrapped API error string for the Tencent error code (e.g. ResourceInUse for duplicate, AuthFailure for perms).
  2. Grant `tag:CreateTag` (and `tag:DeleteTag`, `tag:DescribeTags`) to the principal in CAM.
  3. If the tag already exists from a stale lock, run `terraform force-unlock <ID>` or delete the `tencentcloud-terraform-lock` tag manually, then retry.
  4. 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

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


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 nil

View on GitHub (pinned to d32a084675)