hashicorp/terraform · error

error deleting workspace

Error message

error deleting workspace %s: %v

What it means

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.

Solutions

  1. Ensure all resources in the workspace are destroyed first (terraform destroy without -deletion) before workspace deletion
  2. Verify the authenticated identity has admin or delete-workspace permission on the workspace
  3. Check that no active run holds a lock on the workspace
  4. If SafeDelete is the issue, retry with force=true (equivalent to non-safe delete) if resource cleanup is confirmed
  5. Retry after transient TFE server errors
Defensive patterns

Strategy: validation

Validate before calling

// Before Delete, verify the workspace is empty and deletable:
ws, err := tfeClient.Workspaces.Read(ctx, organization, workspaceName)
if err != nil {
    return err
}
if ws.Locked {
    return fmt.Errorf("workspace %s is locked; cannot delete", workspaceName)
}
if ws.Permissions.CanForceDelete != nil && !*ws.Permissions.CanForceDelete {
    return fmt.Errorf("workspace %s does not support safe delete and force was not requested", workspaceName)
}

Try / catch

err := state.Delete(force)
if err != nil && strings.Contains(err.Error(), "error deleting workspace") {
    if isRetryableError(err) {
        time.Sleep(5 * time.Second)
        return state.Delete(force)
    }
    // if SafeDelete failed, retry with force if the caller permits
    if !force {
        return state.Delete(true)
    }
}
return err

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/4a1bd5d7ca01edb3. Report an issue: GitHub.

Appendix: source

Thrown at internal/cloud/state.go:534

		return lockErr
	}

	return nil
}

// Delete the remote state.
func (s *State) Delete(force bool) error {
	var err error

	isSafeDeleteSupported := s.workspace.Permissions.CanForceDelete != nil
	if force || !isSafeDeleteSupported {
		err = s.tfeClient.Workspaces.Delete(context.Background(), s.organization, s.workspace.Name)
	} else {
		err = s.tfeClient.Workspaces.SafeDelete(context.Background(), s.organization, s.workspace.Name)
	}

	if err != nil && err != tfe.ErrResourceNotFound {
		return fmt.Errorf("error deleting workspace %s: %v", s.workspace.Name, err)
	}

	return nil
}

// GetRootOutputValues fetches output values from HCP Terraform
func (s *State) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {
	// The cloud backend initializes this value to true, but we want to implement
	// some custom retry logic. This code presumes that the tfeClient doesn't need
	// to be shared with other goroutines by the caller.
	s.tfeClient.RetryServerErrors(false)
	defer s.tfeClient.RetryServerErrors(true)

	ctx, cancel := context.WithTimeout(ctx, time.Minute)
	defer cancel()

	var so *tfe.StateVersionOutputsList
	err := RetryBackoff(ctx, func() error {

View on GitHub (pinned to d32a084675)