Loading...
Loading...
### Terraform Version ``` Terraform v1.15.8 on windows_amd64 ``` (Reproduced against `main` as of 2026-09-01 by reading `internal/cloud/backend.go` — the relevant code path is unchanged, so this affects the latest release, 1.16.0, as well.) ### Use cases We use HCP Terraform's key/value **tag bindings** (the newer tagging feature tied to Projects, distinct from the legacy free-form "tag-names" list) to group related workspaces — e.g. two workspaces sharing `Configuration = myapp` (one per environment). We want a single root module to attach to whichever workspace matches via: ```hcl cloud { organization = "my-org" workspaces { tags = { Configuration = "myapp" } } } ``` ### Attempted Solutions Per the [docs](https://developer.hashicorp.com/terraform/cli/cloud/settings#tags), the map form of `workspaces.tags` should match workspaces by key/value tag binding (requires Terraform 1.10+; we're on 1.15.8). We confirmed via the HCP Terraform API that two workspaces in the org carry the exact tag binding we're targeting: ``` GET /api/v2/organizations/my-org/workspaces/my-workspace/tag-bindings { "data": [ { "attributes": { "key": "Configuration", "value": "myapp" } }, ... ] } ``` We also confirmed the API's own tag-binding filter finds both workspaces correctly: ``` GET /api/v2/organizations/my-org/workspaces?filter[tagged][0][key]=Configuration&filter[tagged][0][value]=myapp → 2 matches (both expected workspaces) ``` But `terraform init` with the `tags = { Configuration = "myapp" }` config above always reports: ``` Initializing HCP Terraform... HCP Terraform configuration has changed. No workspaces found. There are no workspaces with the configured tags (Configuration=myapp) in your HCP Terraform organization. To finish initializing, Terraform needs at least one workspace available. Terraform can create a properly tagged workspace for you now. Please enter a name to create a new HCP Terraform workspace. Enter a value: ``` ...even though matching workspaces already exist. ### Root cause (found by reading the source) In [`internal/cloud/backend.go`](https://github.com/hashicorp/terraform/blob/main/internal/cloud/backend.go), `Cloud.Workspaces()` builds the list request like this: ```go } else if b.WorkspaceMapping.Strategy() == WorkspaceKVTagsStrategy { options.TagBindings = b.WorkspaceMapping.asTFETagBindings() // Populate keys, too, just in case backend does not support key/value tags. // The backend will end up applying both filters but that should always // be the same result set anyway. for _, tag := range options.TagBindings { if options.Tags != "" { options.Tags = options.Tags + "," } options.Tags = options.Tags + tag.Key } } ``` This sets **both**: - `options.TagBindings` → correctly encoded by go-tfe as `filter[tagged][0][key]=Configuration&filter[tagged][0][value]=myapp` - `options.Tags` → encoded as the legacy `search[tags]=Configuration` (just the tag *key* name, with no value) The comment assumes the backend "will end up applying both filters but that should always be the same result set anyway" — that assumption is wrong. Based on our reproduction below, HCP Terraform's API appears to apply `filter[tagged]` (key/value tag-binding match) and `search[tags]` (legacy tag-*name* match) as an **AND** (this combined behavior isn't documented; we're inferring it from the observed results). `search[tags]=Configuration` only matches a workspace that has a legacy tag literally named `"Configuration"` — which is a different, older feature (a plain list of tag-name strings, unrelated to key/value tag bindings) and is empty for workspaces that only use key/value tag bindings. So the combined query returned zero results in our testing for an org that uses key/value tags without *also* separately maintaining matching legacy tag-names. We reproduced this precisely by replaying the exact query the CLI sends against the raw API: ``` GET /api/v2/organizations/my-org/workspaces?filter[tagged][0][key]=Configuration&filter[tagged][0][value]=myapp&search[tags]=Configuration → 0 matches ``` vs. the same query without the extra `search[tags]` param → 2 matches. This isolates the bug to that one added-for-safety `options.Tags` fallback in `Workspaces()`. ### Expected Behavior `terraform init` (and `terraform workspace list`) should find the workspaces that match the configured key/value tag bindings, the same way the HCP Terraform API itself does when queried with only `filter[tagged]`. ### Actual Behavior `terraform init` reports "No workspaces found" and offers to create a new (duplicate) workspace, even though matching workspaces exist — for **any** organization that uses key/value tag bindings without also manually duplicating the tag keys as legacy tag-names. This makes the documented map-form `workspaces.tags` feature unusable as shipped. ### Steps to Reproduce 1. In an HCP Terraform org, tag two or more workspaces with the same key/value tag binding (e.g. via the UI's Project tags feature, or `POST /workspaces/:id/tag-bindings`), and make sure none of those workspaces has a legacy tag-name equal to the key you used. 2. Configure a root module: ```hcl terraform { cloud { organization = "my-org" workspaces { tags = { Configuration = "myapp" } } } } ``` 3. Run `terraform init`. ### Suggested fix In `Cloud.Workspaces()` (`internal/cloud/backend.go`), stop unconditionally appending `options.Tags` from the tag-binding keys when using `WorkspaceKVTagsStrategy`. At minimum, this fallback should only be used if a first request with just `options.TagBindings` set returns zero results and the API indicates it doesn't support `filter[tagged]` at all (e.g. via `ErrCloudDoesNotSupportKVTags`, which this same file already detects elsewhere in `workspaceTagsRequireUpdate`). Sending both filters unconditionally as an AND silently breaks the documented feature for the far more common case: an HCP Terraform org that *does* support key/value tags but has never used the older legacy tag-names feature. ### Additional context - `terraform version`: 1.15.8 (bug also present on `main`/1.16.0 — code path unchanged) - go-tfe: v1.105.0 (its `filter[tagged]` encoding in `tag.go`/`encodeTagFiltersAsParams` is correct in isolation — verified against the raw API) - Confirmed via direct HCP Terraform API calls that the workspaces are tagged correctly and are found when queried the same way the CLI does, minus the erroneous extra parameter. --- Co-authored by Claude Sonnet 5
Click on a version to see all relevant bugs
Terraform Integration
Learn more about where this data comes from
BugZero Plan
Streamline upgrades with automated vendor bug scrubs
BugZero Prevent
Wish you caught this bug sooner? Get proactive today.