hashicorp/nomad · error

[✘] Could not create Vault role

Error message

[✘] Could not create Vault role: %w

What it means

After marshaling, createRole writes the role JSON to auth/<path>/role/<role> via Vault's logical WriteBytes API. If the write fails for any reason (auth, connectivity, permissions, invalid role config), the error is wrapped with this message.

Solutions

  1. Verify the Vault token has update capability on auth/<path>/role/+
  2. Confirm Vault address/namespace flags are correct and Vault is unsealed
  3. Check the role JSON (e.g. token_policies referencing existing policies) is valid
  4. Read the wrapped underlying Vault API error for the specific API response
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check: token capabilities
// vault token capabilities auth/<path>/role/<role>  # expect: update

Try / catch

var apiErr *api.ResponseError
if err != nil && errors.As(err, &apiErr) {
    // inspect apiErr.StatusCode / apiErr.Errors for the Vault rejection reason
}

Prevention

When it happens

Trigger: s.vLogical.WriteBytes("auth/<vaultPath>/role/<vaultRole>", buf) returns an error: Vault unreachable, token lacks sudo/update on the auth role path, or the role config is rejected (e.g. bad bound_claims or policies).

Common situations: Vault token without sufficient policy; Vault sealed or unreachable; wrong -vault-path; role referencing a policy that doesn't exist; Vault in namespace mismatch.

Related errors


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

Appendix: source

Thrown at command/setup_vault.go:451

		return role, fmt.Errorf("[✘] Role data could not be deserialized: %w", err)
	}

	role["bound_audiences"] = vaultAud

	return role, nil
}

func (s *SetupVaultCommand) createRole(role map[string]any) error {
	buf, err := json.Marshal(role)
	if err != nil {
		return fmt.Errorf("[✘] Role could not be interpolated with args: %w", err)
	}

	path := fmt.Sprintf("auth/%s/role/%s", vaultPath, vaultRole)

	_, err = s.vLogical.WriteBytes(path, buf)
	if err != nil {
		return fmt.Errorf("[✘] Could not create Vault role: %w", err)
	}

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

func (s *SetupVaultCommand) policyExists() bool {
	existingPolicies, _ := s.vClient.Sys().ListPolicies()
	return slices.Contains(existingPolicies, vaultPolicyName)
}

func (s *SetupVaultCommand) renderPolicy() (string, error) {
	secret, err := s.vLogical.Read("sys/auth/" + vaultPath)
	if err != nil {
		return "", fmt.Errorf("[✘] Could not retrieve JWT accessor: %w", err)
	}
	accessor := secret.Data["accessor"].(string)

View on GitHub (pinned to 482b49bf1a)