hashicorp/terraform · error

state name not allow to be empty

Error message

state name not allow to be empty

What it means

Backend.client(name) builds a remoteClient whose stateFile and lockFile are derived from the name. It rejects empty or whitespace-only names with strings.TrimSpace(name) == "" because the resulting object key would be malformed.

Solutions

  1. Pass a non-empty workspace name.
  2. Use `terraform workspace new/select <name>` with a valid, non-empty name.
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty workspace names before invoking the backend.
func safeClient(b *Backend, name string) (*remoteClient, error) {
    if strings.TrimSpace(name) == "" {
        return nil, fmt.Errorf("state name not allow to be empty")
    }
    return b.client(name)
}

Type guard

// isValidWorkspaceName reports whether name is usable for the COS backend.
func isValidWorkspaceName(name string) bool {
    return strings.TrimSpace(name) != ""
}

Prevention

When it happens

Trigger: b.client("") or b.client(" ") invoked from DeleteWorkspace/StateMgr.

Common situations: Bug in workspace-name plumbing upstream; a script calling the backend API with an empty workspace name; a workspace created with an empty name through some unsupported path.

Related errors


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

Appendix: source

Thrown at internal/backend/remote-state/cos/backend_state.go:156

			if err := stateMgr.PersistState(nil); err != nil {
				err = lockUnlock(err)
				return nil, diags.Append(err)
			}
		}

		// Unlock, the state should now be initialized
		if err := lockUnlock(nil); err != nil {
			return nil, diags.Append(err)
		}
	}

	return stateMgr, diags
}

// client returns a remoteClient for the named state.
func (b *Backend) client(name string) (*remoteClient, error) {
	if strings.TrimSpace(name) == "" {
		return nil, fmt.Errorf("state name not allow to be empty")
	}

	return &remoteClient{
		cosContext: b.cosContext,
		cosClient:  b.cosClient,
		tagClient:  b.tagClient,
		bucket:     b.bucket,
		stateFile:  b.stateFile(name),
		lockFile:   b.lockFile(name),
		encrypt:    b.encrypt,
		acl:        b.acl,
	}, nil
}

// stateFile returns state file path by name
func (b *Backend) stateFile(name string) string {
	if name == backend.DefaultStateName {
		return path.Join(b.prefix, b.key)

View on GitHub (pinned to d32a084675)