{"record":{"id":"ade6663d1971f9fc","repo":"hashicorp/terraform","slug":"q-is-not-a-valid-state-name","errorCode":null,"errorMessage":"%q is not a valid state name","messagePattern":"%q is not a valid state name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/backend_state.go","lineNumber":83,"sourceCode":"// DeleteWorkspace deletes the named workspaces. The \"default\" state cannot be deleted.\nfunc (b *Backend) DeleteWorkspace(name string, _ bool) tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\tif name == backend.DefaultStateName {\n\t\treturn diags.Append(fmt.Errorf(\"cowardly refusing to delete the %q state\", name))\n\t}\n\n\tc, err := b.client(name)\n\tif err != nil {\n\t\treturn diags.Append(err)\n\t}\n\n\treturn diags.Append(c.Delete())\n}\n\n// client returns a remoteClient for the named state.\nfunc (b *Backend) client(name string) (*remoteClient, error) {\n\tif name == \"\" {\n\t\treturn nil, fmt.Errorf(\"%q is not a valid state name\", name)\n\t}\n\n\treturn &remoteClient{\n\t\tstorageClient: b.storageClient,\n\t\tbucketName:    b.bucketName,\n\t\tstateFilePath: b.stateFile(name),\n\t\tlockFilePath:  b.lockFile(name),\n\t\tencryptionKey: b.encryptionKey,\n\t\tkmsKeyName:    b.kmsKeyName,\n\t}, nil\n}\n\n// StateMgr reads and returns the named state from GCS. If the named state does\n// not yet exist, a new state file is created.\nfunc (b *Backend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {\n\tvar diags tfdiags.Diagnostics\n\n\tc, err := b.client(name)","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/gcs/backend_state.go#L65-L101","documentation":"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().","triggerScenarios":"Programmatic use of the Backend interface with StateMgr(\"\") or DeleteWorkspace(\"\", _); a wrapper tool that computes workspace names and produces an empty string.","commonSituations":"Tooling/automation bugs that pass an unset variable as the workspace name; misconfigured workspace-name interpolation in HCL-driven automation.","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)."],"exampleFix":"// before\nmgr, diags := backend.StateMgr(os.Getenv(\"TF_WORKSPACE\"))  // empty when unset\n\n// after\nname := os.Getenv(\"TF_WORKSPACE\")\nif name == \"\" { name = backend.DefaultStateName }\nmgr, diags := backend.StateMgr(name)","handlingStrategy":"validation","validationCode":"name := os.Getenv(\"TF_WORKSPACE\")\nif name == \"\" { name = backend.DefaultStateName }\nmgr, diags := backend.StateMgr(name)","typeGuard":"func isValidStateName(name string) bool { return strings.TrimSpace(name) != \"\" }","tryCatchPattern":null,"preventionTips":["Default empty workspace inputs to backend.DefaultStateName.","Validate non-empty before calling StateMgr/DeleteWorkspace.","Unit-test callers with empty-string inputs."],"tags":["gcs","gcp","workspaces","validation","config-validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}