hashicorp/terraform · error
can't delete default state
Error message
can't delete default state
What it means
Thrown by Backend.DeleteWorkspace in the S3 state backend when name equals backend.DefaultStateName ("default") or "". Same guard as the pg backend: the default workspace is the canonical state and cannot be deleted through this API. The check runs before the remote client Delete() so no S3 object is touched.
Solutions
- Filter out 'default' and empty lines in any workspace-deletion loop.
- Use `tofu destroy` to clear default state instead of deleting the workspace.
- Validate workspace names from upstream config before calling delete.
Example fix
# before for ws in $(tofu workspace list | tr -d '*'); do tofu workspace delete "$ws"; done # after for ws in $(tofu workspace list | tr -d '*' | grep -v '^default$'); do tofu workspace delete "$ws"; done
Defensive patterns
Strategy: validation
Validate before calling
func deleteWorkspace(name string) error {
if name == backend.DefaultStateName || name == "" {
return fmt.Errorf("protected workspace %q; use `tofu destroy` instead", name)
}
// ... proceed
} Prevention
- Filter 'default' out of workspace-deletion loops.
- Validate upstream workspace-name inputs before delete.
- Use `tofu destroy` to clear default state.
When it happens
Trigger: DeleteWorkspace(name, _) called with name == "default" or "". Triggered by `tofu workspace delete default` or any loop that tries to delete every workspace including default.
Common situations: Teardown script enumerating `tofu workspace list` and deleting each line; CI that auto-creates and deletes ephemeral workspaces but fails to skip default; misunderstanding default-state immutability.
Related errors
- can't delete default state
- can't delete default state
- can't delete default state
- can't delete default state
- Error unlocking S3 state. Lock ID
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/4416d6a984dc53d1.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/s3/backend_state.go:142
// not our key, so don't include it in our listing
if parts[1] != b.keyName {
return ""
}
return parts[0]
}
func (b *Backend) DeleteWorkspace(name string, _ bool) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
log := logger()
log = logWithOperation(log, operationBackendDeleteWorkspace)
log = log.With(
logKeyBackendWorkspace, name,
)
if name == backend.DefaultStateName || name == "" {
return diags.Append(fmt.Errorf("can't delete default state"))
}
log.Info("Deleting workspace")
client, err := b.remoteClient(name)
if err != nil {
return diags.Append(err)
}
return diags.Append(client.Delete())
}
// get a remote client configured for this state
func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
if name == "" {
return nil, errors.New("missing state name")
}
View on GitHub (pinned to d32a084675)