{"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/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/cloud/state.go#L516-L552","documentation":"Thrown by the Delete method when Workspaces.Delete (or Workspaces.SafeDelete) fails for any reason other than tfe.ErrResourceNotFound (which is silently ignored since the workspace is already gone). The error includes the workspace name. SafeDelete is used when the workspace supports it (Permissions.CanForceDelete is non-nil) and force is false; otherwise a hard Delete is performed.","triggerScenarios":"SafeDelete fails because the workspace is not empty (has resources/state) and cannot be safely removed; the authenticated user lacks admin/delete permission on the workspace; the workspace is currently locked by an active run; network or TFE server error; attempting to delete a workspace that still has pending state version uploads.","commonSituations":"Running 'terraform destroy' with workspace deletion enabled on a workspace that still has unmanaged resources; CI service account without workspace-delete permission; workspace locked by a long-running apply; SafeDelete supported but workspace has non-empty resource count.","solutions":["Ensure all resources in the workspace are destroyed first (terraform destroy without -deletion) before workspace deletion","Verify the authenticated identity has admin or delete-workspace permission on the workspace","Check that no active run holds a lock on the workspace","If SafeDelete is the issue, retry with force=true (equivalent to non-safe delete) if resource cleanup is confirmed","Retry after transient TFE server errors"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before Delete, verify the workspace is empty and deletable:\nws, err := tfeClient.Workspaces.Read(ctx, organization, workspaceName)\nif err != nil {\n    return err\n}\nif ws.Locked {\n    return fmt.Errorf(\"workspace %s is locked; cannot delete\", workspaceName)\n}\nif ws.Permissions.CanForceDelete != nil && !*ws.Permissions.CanForceDelete {\n    return fmt.Errorf(\"workspace %s does not support safe delete and force was not requested\", workspaceName)\n}","typeGuard":null,"tryCatchPattern":"err := state.Delete(force)\nif err != nil && strings.Contains(err.Error(), \"error deleting workspace\") {\n    if isRetryableError(err) {\n        time.Sleep(5 * time.Second)\n        return state.Delete(force)\n    }\n    // if SafeDelete failed, retry with force if the caller permits\n    if !force {\n        return state.Delete(true)\n    }\n}\nreturn err","preventionTips":["Destroy all resources (terraform destroy) before attempting workspace deletion","Verify the service account has workspace-delete permission before running destroy with deletion","Ensure no active run holds a lock on the workspace before deletion"],"tags":["workspace","deletion","tfe","permissions","terraform"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}