hashicorp/terraform · error

Error creating workspace

Error message

Error creating workspace %s: %v

What it means

Thrown after Workspaces.Read returned NotFound and the backend attempted to auto-create the workspace via Workspaces.Create. The create call failed. This path only runs when the workspace does not yet exist and the backend is permitted to auto-provision it.

Solutions

  1. Inspect the wrapped error (%v) for the precise API rejection reason.
  2. Grant the token's team 'Admin' or 'Create Workspaces' permission on the organization, or pre-create the workspace in the UI.
  3. Fix the workspace name to be lowercase, alphanumeric, with only '-' or '_' separators.
  4. If a quota is hit, free up a workspace slot or request a quota increase, then retry 'terraform init'.

Example fix

// before: name derived from user input with spaces
name = "My Workspace"
// after: normalize the workspace name
name = strings.ToLower(strings.ReplaceAll("My Workspace", " ", "-"))
Defensive patterns

Strategy: validation

Validate before calling

// Validate workspace name rules (TFC: lowercase, URL-safe) before relying on auto-create.
var wsNameRe = regexp.MustCompile(`^[a-z0-9][a-z0-9-_]{0,90}$`)
func validWorkspaceName(name string) bool { return wsNameRe.MatchString(name) }

Try / catch

// On create failure, branch on the wrapped status.
if _, err := b.client.Workspaces.Create(ctx, org, opts); err != nil {
    if isStatus(err, 403) { /* grant Create permission */ }
    if isStatus(err, 409) { /* name conflict / soft-deleted */ }
}

Prevention

When it happens

Trigger: b.client.Workspaces.Create(ctx, org, options) returns an error. Common: token/team lacks 'Create Workspace' permission on the org; workspace name fails validation (invalid characters, too long); org workspace quota exceeded; name collides with a soft-deleted workspace.

Common situations: Using a read-only service token in CI; workspace name with uppercase letters or spaces (TFC requires lowercase, URL-safe); exceeding the org's workspace limit; TFE project with restricted workspace creation.

Related errors


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

Appendix: source

Thrown at internal/backend/remote/backend.go:687

	workspace, err := b.client.Workspaces.Read(context.Background(), b.organization, name)
	if err != nil && err != tfe.ErrResourceNotFound {
		return nil, diags.Append(fmt.Errorf("Failed to retrieve workspace %s: %v", name, err))
	}

	if err == tfe.ErrResourceNotFound {
		options := tfe.WorkspaceCreateOptions{
			Name: tfe.String(name),
		}

		// We only set the Terraform Version for the new workspace if this is
		// a release candidate or a final release.
		if tfversion.Prerelease == "" || strings.HasPrefix(tfversion.Prerelease, "rc") {
			options.TerraformVersion = tfe.String(tfversion.String())
		}

		workspace, err = b.client.Workspaces.Create(context.Background(), b.organization, options)
		if err != nil {
			return nil, diags.Append(fmt.Errorf("Error creating workspace %s: %v", name, err))
		}
	}

	// This is a fallback error check. Most code paths should use other
	// mechanisms to check the version, then set the ignoreVersionConflict
	// field to true. This check is only in place to ensure that we don't
	// accidentally upgrade state with a new code path, and the version check
	// logic is coarser and simpler.
	if !b.ignoreVersionConflict {
		wsv := workspace.TerraformVersion
		// Explicitly ignore the pseudo-version "latest" here, as it will cause
		// plan and apply to always fail.
		if wsv != tfversion.String() && wsv != "latest" {
			return nil, diags.Append(fmt.Errorf("Remote workspace Terraform version %q does not match local Terraform version %q", workspace.TerraformVersion, tfversion.String()))
		}
	}

	client := &remoteClient{

View on GitHub (pinned to d32a084675)