hashicorp/terraform · error
failed to create project
Error message
failed to create project %s: %v
What it means
Thrown by the Cloud backend when auto-creating a TFE/HCP project named in the `cloud { project = ... }` block. The backend first attempted a lookup that returned nothing, then called Projects.Create; any failure other than tfe.ErrResourceNotFound is surfaced here. ErrResourceNotFound from Create is intentionally swallowed (it signals the projects feature is absent), but every other API failure (auth, name conflict, validation, transport) propagates.
Solutions
- Pre-create the project in the TFE/HCP UI (or via API) and keep the cloud block referencing its name so Create is never attempted.
- Grant the service token organization-level 'Manage Projects' (or admin) permission so Projects.Create succeeds.
- Sanitize the project name to [A-Za-z0-9_-] and stay within length limits before running init.
- For concurrent pipelines racing on a new project, gate project creation behind a single job or use an external provisioner.
Example fix
// before
cloud {
organization = "acme"
project = "Team A Workspace!"
workspaces { name = "prod" }
}
// after
cloud {
organization = "acme"
project = "team-a"
workspaces { name = "prod" }
} Defensive patterns
Strategy: validation
Validate before calling
// before init, preflight project creation prerequisites
func canCreateProject(client *tfe.Client, org, project string) error {
if !regexp.MustCompile(`^[A-Za-z0-9_-]+$`).MatchString(project) {
return fmt.Errorf("project name %q has invalid characters", project)
}
// verify org is reachable and token has admin scope
if _, err := client.Organizations.Read(ctx, org); err != nil {
return fmt.Errorf("cannot read org %s: %w", org, err)
}
// if project already exists, Create won't be attempted
if p, err := client.Projects.Read(ctx, org, project); err == nil {
_ = p // exists, safe
} else if err != tfe.ErrResourceNotFound {
return err
}
return nil
} Prevention
- Pre-create projects out-of-band so the auto-create path never runs.
- Give the init token org-level project-management scope, or none and pre-create.
- Validate project names against [A-Za-z0-9_-] before applying.
- Serialize concurrent `init` runs that target a brand-new project name.
When it happens
Trigger: b.client.Projects.Create(ctx, b.Organization, createOpts) returns err != nil AND err != tfe.ErrResourceNotFound. Concretely: 401/403 when the token lacks org-level project-management scope; 409 if a project with that name appears between the lookup and the create (race); 422 for names with illegal characters; 5xx or network/timeout from the TFE/TFE-instance host.
Common situations: A user adds `project = "team-a"` to a cloud block expecting auto-creation, but the API token only has workspace-level permissions. Or two developers running `terraform init` simultaneously against a fresh project name. Or a project name containing spaces/slashes that the API rejects.
Related errors
- error creating workspace
- error updating workspace
- workspace not found For security, returns '404 Not Found'…
- backend does not support key/value tags. Try using key-only…
- Error asking
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/11b927aa90dfc86c.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/backend.go:799
if b.WorkspaceMapping.Strategy() == WorkspaceTagsStrategy {
workspaceCreateOptions.Tags = b.WorkspaceMapping.tfeTags()
} else if b.WorkspaceMapping.Strategy() == WorkspaceKVTagsStrategy {
workspaceCreateOptions.TagBindings = b.WorkspaceMapping.asTFETagBindings()
}
// Create project if not exists, otherwise use it
if workspaceCreateOptions.Project == nil && b.WorkspaceMapping.Project != "" {
// If we didn't find the project, try to create it
if workspaceCreateOptions.Project == nil {
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.View on GitHub (pinned to d32a084675)