{"record":{"id":"4a1bd5d7ca01edb3","repo":"hashicorp/terraform","slug":"error-deleting-workspace-s-v-4a1bd5","errorCode":null,"errorMessage":"error deleting workspace %s: %v","messagePattern":"error deleting workspace (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloud/state.go","lineNumber":534,"sourceCode":"\t\treturn lockErr\n\t}\n\n\treturn nil\n}\n\n// Delete the remote state.\nfunc (s *State) Delete(force bool) error {\n\tvar err error\n\n\tisSafeDeleteSupported := s.workspace.Permissions.CanForceDelete != nil\n\tif force || !isSafeDeleteSupported {\n\t\terr = s.tfeClient.Workspaces.Delete(context.Background(), s.organization, s.workspace.Name)\n\t} else {\n\t\terr = s.tfeClient.Workspaces.SafeDelete(context.Background(), s.organization, s.workspace.Name)\n\t}\n\n\tif err != nil && err != tfe.ErrResourceNotFound {\n\t\treturn fmt.Errorf(\"error deleting workspace %s: %v\", s.workspace.Name, err)\n\t}\n\n\treturn nil\n}\n\n// GetRootOutputValues fetches output values from HCP Terraform\nfunc (s *State) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {\n\t// The cloud backend initializes this value to true, but we want to implement\n\t// some custom retry logic. This code presumes that the tfeClient doesn't need\n\t// to be shared with other goroutines by the caller.\n\ts.tfeClient.RetryServerErrors(false)\n\tdefer s.tfeClient.RetryServerErrors(true)\n\n\tctx, cancel := context.WithTimeout(ctx, time.Minute)\n\tdefer cancel()\n\n\tvar so *tfe.StateVersionOutputsList\n\terr := RetryBackoff(ctx, func() error {","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/cloud/state.go#L516-L552","documentation":"Delete(force) removes the workspace via Workspaces.Delete (or Workspaces.SafeDelete when supported and force is false). Any failure other than ErrResourceNotFound is wrapped here. It usually means the workspace is not in a deletable state or the token lacks permission.","triggerScenarios":"Deleting a workspace that still has state versions, is currently locked, has pending runs, or for which the token lacks delete permission; the API returns 4xx/5xx.","commonSituations":"Calling SafeDelete on a non-empty workspace (it refuses), deleting a locked workspace, or an insufficiently-scoped token.","solutions":["Pass force=true if you intend to destroy state/resources along with the workspace.","Unlock the workspace before deleting it.","Confirm the token has admin/delete permission on the workspace.","Verify the workspace has no pending runs.","Retry on a 5xx response."],"exampleFix":"// before: safe-delete a non-empty workspace -> error deleting workspace\nstate.Delete(false)\n\n// after: force-delete once you are sure state/resources should be destroyed\nstate.Delete(true)","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure the workspace is deletable before calling Delete\nws, err := client.Workspaces.Read(ctx, org, name)\nif err == nil {\n    if ws.Locked {\n        return errors.New(\"workspace is locked; unlock before deleting\")\n    }\n    if ws.Permissions.CanForceDelete != nil && !*ws.Permissions.CanForceDelete {\n        return errors.New(\"token lacks delete permission on the workspace\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := state.Delete(force); err != nil {\n    if errors.Is(err, tfe.ErrResourceNotFound) {\n        return nil // already gone\n    }\n    return err\n}","preventionTips":["Unlock the workspace before deleting","Use force=true only when state/resources should be destroyed","Confirm the token has delete permission"],"tags":["workspace","deletion","cleanup","permissions"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}