hashicorp/nomad · error

[✘] Could not create Consul role: %w

Error message

[✘] Could not create Consul role: %w

What it means

createRoleForTasks creates the 'nomad-workloads' Consul role (linking the nomad-workloads policy) via ACL().RoleCreate. Any API error — connectivity, insufficient token privileges, invalid policy link, or role name conflict — is wrapped here.

Source

Thrown at command/setup_consul.go:558

	return nil
}

func (s *SetupConsulCommand) roleExists() bool {
	existingRoles, _, _ := s.client.ACL().RoleList(nil)
	return slices.ContainsFunc(
		existingRoles,
		func(r *api.ACLRole) bool { return r.Name == consulRoleTasks })
}

func (s *SetupConsulCommand) createRoleForTasks() error {
	_, _, err := s.client.ACL().RoleCreate(&api.ACLRole{
		Name:        consulRoleTasks,
		Description: "Role for Nomad tasks using workload identities",
		Policies:    []*api.ACLLink{{Name: consulPolicyName}},
	}, nil)
	if err != nil {
		return fmt.Errorf("[✘] Could not create Consul role: %w", err)
	}

	s.Ui.Info(fmt.Sprintf("[✔] Created role %q.", consulRoleTasks))
	return nil
}

func (s *SetupConsulCommand) policyExists() bool {
	existingPolicies, _, _ := s.client.ACL().PolicyList(nil)
	return slices.ContainsFunc(
		existingPolicies,
		func(p *api.ACLPolicyListEntry) bool { return p.Name == consulPolicyName })
}

func (s *SetupConsulCommand) createPolicy() error {
	_, _, err := s.client.ACL().PolicyCreate(&api.ACLPolicy{
		Name:  consulPolicyName,
		Rules: string(consulPolicyBody),
	}, nil)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check token privileges: `consul acl token read -self`; export CONSUL_HTTP_TOKEN with acl:write (management token is simplest).
  2. Verify the policy exists: `consul acl policy list | grep nomad-workloads`; re-run setup or create the policy first if it's missing.
  3. Confirm connectivity to the Consul agent (`consul members`, CONSUL_HTTP_ADDR) and inspect the wrapped error for the exact API message.
  4. If the role exists in a broken state, `consul acl role delete -name nomad-workloads` (or update it) then re-run nomad setup.

Example fix

# before
nomad setup consul   # read-only token -> RoleCreate denied
// after
export CONSUL_HTTP_TOKEN=<management-token>
nomad setup consul
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: policy must exist and token must write ACLs
pols, _, err := s.client.ACL().PolicyList(nil)
if err != nil { return err }
var hasPolicy bool
for _, p := range pols { if p.Name == "nomad-workloads" { hasPolicy = true } }
if !hasPolicy { return fmt.Errorf("policy nomad-workloads missing; create it before the role") }
_, _, err = s.client.ACL().RoleList(nil)
if err != nil { return fmt.Errorf("token cannot manage roles: %v", err) }

Try / catch

_, _, err := s.client.ACL().RoleCreate(role, nil)
if err != nil {
    if strings.Contains(err.Error(), "Permission denied") {
        return fmt.Errorf("token lacks acl:write; set CONSUL_HTTP_TOKEN to a privileged token: %w", err)
    }
    return fmt.Errorf("[✘] Could not create Consul role: %w", err)
}

Prevention

When it happens

Trigger: `nomad setup consul` calls RoleCreate and errors: Consul agent unreachable, the Consul token lacks acl:write (roles require management-level or appropriate privileges), or the referenced policy 'nomad-workloads' doesn't exist because createPolicy failed earlier in the sequence.

Common situations: CONSUL_HTTP_TOKEN missing or under-privileged (role creation typically needs acl:write); prior step failed so the policy link is invalid; wrong CONSUL_HTTP_ADDR; a role named nomad-workloads already exists in a conflicting state after a partially-failed setup.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/42abf595e81b5e68. Report an issue: GitHub.