hashicorp/terraform · error

error creating workspace

Error message

error creating workspace %s: %v

What it means

Returned when b.client.Workspaces.Create fails for the resolved workspace name. This is the terminal step of the create-workspace path: project (if any) was resolved above, then the workspace POST itself errored. The wrapped %v is the raw TFE client error, so HTTP status and API message travel with it.

Solutions

  1. Verify the workspace name matches TFE naming rules (lowercase alphanumerics, _, -, max 90 chars) and rerun.
  2. Confirm the API token has 'Workspaces: Admin' / create scope on the target organization.
  3. Check the organization spelling in the cloud block and the hostname in `hostname`.
  4. If the workspace already exists, do not rely on auto-create—reference it explicitly and ensure the token can read it.
  5. For races, serialize `init` across CI agents or pre-create the workspace.

Example fix

// before
cloud {
  organization = "acme"
  workspaces { name = "Prod Env" }
}

// after
cloud {
  organization = "acme"
  workspaces { name = "prod-env" }
}
Defensive patterns

Strategy: validation

Validate before calling

func validWorkspaceName(name string) error {
    if name == "" || len(name) > 90 {
        return fmt.Errorf("workspace name length invalid")
    }
    if !regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`).MatchString(name) {
        return fmt.Errorf("workspace name %q must be lowercase alnum/-/_", name)
    }
    return nil
}
// also confirm token scope:
//   Workspaces: Admin on the target organization

Prevention

When it happens

Trigger: Workspaces.Create(ctx, org, workspaceCreateOptions) returns non-nil err: 409 workspace name already exists in the org; 422 for invalid name or duplicate-when-not-allowed; 401/403 if the token cannot create workspaces; 404 if the organization itself is wrong; transport/timeout against the TFE host.

Common situations: TF_WORKSPACE points at a name with uppercase letters or spaces; the cloud block's `name` collides with an existing workspace the token can read but not write; the organization string is misspelled so the org lookup 404s into a create failure; an auto-create race between two `terraform init` runs.

Related errors


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

Appendix: source

Thrown at internal/cloud/backend.go:810

				createOpts := tfe.ProjectCreateOptions{
					Name: b.WorkspaceMapping.Project,
				}
				// didn't find project, create it instead
				log.Printf("[TRACE] cloud: Creating %s project %s/%s", b.appName, b.Organization, b.WorkspaceMapping.Project)
				project, err := b.client.Projects.Create(context.Background(), b.Organization, createOpts)
				if err != nil && err != tfe.ErrResourceNotFound {
					return nil, diags.Append(fmt.Errorf("failed to create project %s: %v", b.WorkspaceMapping.Project, err))
				}
				configuredProject = project
				workspaceCreateOptions.Project = configuredProject
			}
		}

		// Create a workspace
		log.Printf("[TRACE] cloud: Creating %s workspace %s/%s", b.appName, b.Organization, name)
		workspace, err = b.client.Workspaces.Create(context.Background(), b.Organization, workspaceCreateOptions)
		if err != nil {
			return nil, diags.Append(fmt.Errorf("error creating workspace %s: %v", name, err))
		}

		remoteTFVersion = workspace.TerraformVersion

		// Attempt to set the new workspace to use this version of Terraform. This
		// can fail if there's no enabled tool_version whose name matches our
		// version string, but that's expected sometimes -- just warn and continue.
		versionOptions := tfe.WorkspaceUpdateOptions{
			TerraformVersion: tfe.String(tfversion.String()),
		}
		_, err := b.client.Workspaces.UpdateByID(context.Background(), workspace.ID, versionOptions)
		if err == nil {
			remoteTFVersion = tfversion.String()
		} else {
			// TODO: Ideally we could rely on the client to tell us what the actual
			// problem was, but we currently can't get enough context from the error
			// object to do a nicely formatted message, so we're just assuming the
			// issue was that the version wasn't available since that's probably what

View on GitHub (pinned to d32a084675)