hashicorp/terraform · error
%q is not a valid state name
Error message
%q is not a valid state name
What it means
Backend.client(name) requires a non-empty workspace name; an empty string produces no valid object key (it would map to '.tfstate'), so the backend rejects it before constructing the remoteClient. Returned from StateMgr, DeleteWorkspace, and any code path that goes through client().
Source
Thrown at internal/backend/remote-state/gcs/backend_state.go:83
// DeleteWorkspace deletes the named workspaces. The "default" state cannot be deleted.
func (b *Backend) DeleteWorkspace(name string, _ bool) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
if name == backend.DefaultStateName {
return diags.Append(fmt.Errorf("cowardly refusing to delete the %q state", name))
}
c, err := b.client(name)
if err != nil {
return diags.Append(err)
}
return diags.Append(c.Delete())
}
// client returns a remoteClient for the named state.
func (b *Backend) client(name string) (*remoteClient, error) {
if name == "" {
return nil, fmt.Errorf("%q is not a valid state name", name)
}
return &remoteClient{
storageClient: b.storageClient,
bucketName: b.bucketName,
stateFilePath: b.stateFile(name),
lockFilePath: b.lockFile(name),
encryptionKey: b.encryptionKey,
kmsKeyName: b.kmsKeyName,
}, nil
}
// StateMgr reads and returns the named state from GCS. If the named state does
// not yet exist, a new state file is created.
func (b *Backend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
c, err := b.client(name)View on GitHub (pinned to c9def3e214)
Solutions
- Ensure the caller passes a concrete non-empty workspace name (commonly 'default').
- Add a guard before invoking StateMgr/DeleteWorkspace: if name == "" { name = backend.DefaultStateName }.
- Trace the caller to find where the empty value originates (env var, flag, list index).
Example fix
// before
mgr, diags := backend.StateMgr(os.Getenv("TF_WORKSPACE")) // empty when unset
// after
name := os.Getenv("TF_WORKSPACE")
if name == "" { name = backend.DefaultStateName }
mgr, diags := backend.StateMgr(name) Defensive patterns
Strategy: validation
Validate before calling
name := os.Getenv("TF_WORKSPACE")
if name == "" { name = backend.DefaultStateName }
mgr, diags := backend.StateMgr(name) Type guard
func isValidStateName(name string) bool { return strings.TrimSpace(name) != "" } Prevention
- Default empty workspace inputs to backend.DefaultStateName.
- Validate non-empty before calling StateMgr/DeleteWorkspace.
- Unit-test callers with empty-string inputs.
When it happens
Trigger: Programmatic use of the Backend interface with StateMgr("") or DeleteWorkspace("", _); a wrapper tool that computes workspace names and produces an empty string.
Common situations: Tooling/automation bugs that pass an unset variable as the workspace name; misconfigured workspace-name interpolation in HCL-driven automation.
Related errors
- cowardly refusing to delete the %q state
- impersonate_service_account_delegates elements must not be n
- Error loading encryption key: %s
- Error decoding encryption key: %s
- querying Cloud Storage failed: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/ade6663d1971f9fc.
Report an issue: GitHub.