hashicorp/terraform · error
default state is not allowed to be deleted
Error message
default state is not allowed to be deleted
What it means
Backend.DeleteWorkspace refuses to delete the workspace whose name is backend.DefaultStateName ('default') or empty. The default workspace is the root state of the backend and cannot be removed through the workspace API.
Solutions
- Do not delete the default workspace. Run terraform destroy first if you want to remove resources.
- If you truly want to remove the state object, manually delete it from the COS bucket at the default stateFile path after destroying.
- Update cleanup scripts to skip name == 'default'.
Defensive patterns
Strategy: validation
Validate before calling
// Reject attempts to delete the default workspace before calling DeleteWorkspace.
func safeDeleteWorkspace(b *Backend, name string) tfdiags.Diagnostics {
if name == backend.DefaultStateName || strings.TrimSpace(name) == "" {
var d tfdiags.Diagnostics
return d.Append(fmt.Errorf("default state is not allowed to be deleted"))
}
return b.DeleteWorkspace(name, false)
} Prevention
- Skip name == 'default' in workspace cleanup automation.
- Run terraform destroy before any manual state removal.
- Document that the default workspace is immutable for delete.
- Audit CI scripts that enumerate and delete workspaces.
When it happens
Trigger: terraform workspace delete default, or the backend's DeleteWorkspace called with name == "default" or "".
Common situations: Automation/CI tries to wipe all workspaces including default; a cleanup script enumerates workspaces and deletes each without skipping default.
Related errors
- state name not allow to be empty
- acl value invalid, expected
- Failed to lock cos state
- Invalid URL: must be
- key can not start and end with '/'
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/8f0365a2372634be.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/cos/backend_state.go:71
parts := strings.Split(strings.TrimPrefix(vv.Key, prefix), "/")
if len(parts) > 0 && parts[0] != "" {
ws = append(ws, parts[0])
}
}
sort.Strings(ws[1:])
log.Printf("[DEBUG] list all workspaces, workspaces: %v", ws)
return ws, diags
}
// DeleteWorkspace deletes the named workspaces. The "default" state cannot be deleted.
func (b *Backend) DeleteWorkspace(name string, _ bool) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
log.Printf("[DEBUG] delete workspace, workspace: %v", name)
if name == backend.DefaultStateName || name == "" {
return tfdiags.Diagnostics{}.Append(fmt.Errorf("default state is not allowed to be deleted"))
}
c, err := b.client(name)
if err != nil {
return diags.Append(err)
}
return diags.Append(c.Delete())
}
// StateMgr manage the state, if the named state not exists, a new file will created
func (b *Backend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
log.Printf("[DEBUG] state manager, current workspace: %v", name)
c, err := b.client(name)
if err != nil {
return nil, diags.Append(err)View on GitHub (pinned to d32a084675)