Terraform 1.16.6 fixes workspace filtering with uppercase tag keys
Terraform 1.16.6 stops sending a redundant workspace tag filter that could exclude valid key/value matches. The patch also allows deprecated outputs in modules under test.
Terraform 1.16.6, released on October 14, corrects workspace selection during initialization when key/value tag keys contain uppercase letters. The release notes describe a discovery failure with a specific cause. Terraform was sending two filters that it expected to identify the same workspaces. Their behavior differed, and the extra filter could exclude the workspace selected by the intended key/value binding.
I use Terraform as a daily driver and value its reusable abstractions over infrastructure APIs. Workspace selection is one of the places where I want that abstraction to be explicit. A configuration can express the intended selector correctly and still fail if the client translates it into a request with additional constraints. This patch repairs that translation without requiring users to rename the affected tag keys.
A compatibility fallback narrowed the result
The patch in pull request 39306 removes code from the cloud backend's workspace listing method. When using the key/value tag strategy, the code already populated TagBindings from the workspace mapping. It then copied each binding's key into the older Tags filter as well. A comment described that second filter as a fallback for backends without key/value tag support.
The assumption was that applying both filters would always produce the same result set. An added regression assertion explains why that assumption failed. The server lowercases the search[tags] filter, which excludes workspaces whose key/value tag keys contain uppercase letters. A request intended to preserve the binding's key therefore also supplied a differently interpreted version of that key.
Two filters applied together are additional constraints, even when a client expects them to be equivalent. If they use different matching rules, their intersection can be smaller than either intended selection. Here, preserving the key/value binding did not help when the redundant filter independently rejected the matching workspace.
The correction leaves the key/value bindings in place and removes the construction of the older tag filter for that strategy. The separate set-of-tags strategy still populates its own filter. This is a scoped request change. It does not claim that the two tag models have become interchangeable or that all server versions interpret them identically.
I would use this as a reminder to inspect the actual request when a selector returns no result. The empty result does not prove the object lacks the configured binding. A client can add a constraint the author did not express directly. Removing that constraint can be the correct fix when the intended selector already has an appropriate representation.
The test checks what the client sends
The regression test retains the existing assertion that the expected workspace is returned. It adds an assertion that the workspace listing options contain no legacy Tags value for key/value selection. The mock workspace client now records the last options passed to its list operation so the test can inspect them.
That assertion is useful because a mock may not reproduce the server's normalization rules. Checking only its returned workspace could allow the redundant filter to remain unnoticed. Inspecting the request proves that Terraform stopped sending the problematic constraint, independently of how much matching behavior the mock implements.
For an affected configuration, I would upgrade the executable and rerun initialization with the same workspace selector:
terraform init
My next check is the selected workspace before proceeding with an infrastructure change. The patch makes the intended workspace discoverable, but a successful initialization still needs to correspond to the operator's intended environment. Changing tag names at the same time would make the original regression harder to verify and could affect other consumers of those tags.
Module tests can retain deprecated outputs
The release also allows a module under test to use deprecated outputs. The reported example shows a reusable module tested directly. Adding a deprecation annotation caused its tests to fail even when they did not consume that output, because the test loaded the module in the root position.
This matters for a compatibility migration. An author may deliberately keep an old output while warning callers to use its replacement. Direct tests still need to examine the module during that transition. The release's correction lets that deprecation remain in the module under test, without requiring the author to remove the annotation solely to run the suite.
I want tests to check the old output's retained value and the replacement's behavior as separate expectations. A deprecation annotation communicates an interface change, while the module's tests establish what the interface still does. Keeping both in the same revision gives reviewers evidence that the warning did not accidentally remove the behavior callers depend on during migration.
For a module author, this means the compatibility warning can remain visible in configuration while the test suite continues to cover the supported interface. The executable upgrade and the module change still deserve separate verification.