hashicorp/nomad · error

computed %q bind name for bind target is invalid: %q

Error message

computed %q bind name for bind target is invalid: %q

What it means

computeBindName successfully interpolated the bind name template, but the resulting string fails the name-validation regex for the rule's bind type (ValidPolicyName or ValidACLRoleName). Bind refuses to bind an invalid role/policy name rather than silently producing an unusable binding.

Source

Thrown at lib/auth/binder.go:96

			matchingRules = append(matchingRules, rule)
			vlog.Debug("binding-rule selector matches an identity claim, will evaluate bind-name", "selector", rule.Selector)
		} else {
			vlog.Debug("bind-rule selector did not match any claims", "selector", rule.Selector)
		}
	}
	if len(matchingRules) == 0 {
		return &bindings, nil
	}

	// Compute role or policy names by interpolating the identity's claim
	// mappings into the rule BindName templates.
	for _, rule := range matchingRules {
		bindName, valid, err := computeBindName(rule.BindType, rule.BindName, identity.ClaimMappings)
		switch {
		case err != nil:
			return nil, fmt.Errorf("cannot compute %q bind name for bind target: %w", rule.BindType, err)
		case !valid:
			return nil, fmt.Errorf("computed %q bind name for bind target is invalid: %q", rule.BindType, bindName)
		}

		switch rule.BindType {
		case structs.ACLBindingRuleBindTypeRole:
			role, err := b.store.GetACLRoleByName(nil, bindName)
			if err != nil {
				return nil, err
			}

			if role != nil {
				bindings.Roles = append(bindings.Roles, &structs.ACLTokenRoleLink{
					ID: role.ID,
				})
				vlog.Debug("role found with name matching ACL binding-rule", "name", bindName)
			} else {
				vlog.Debug("no role found with name matching ACL binding-rule", "name", bindName)
			}
		case structs.ACLBindingRuleBindTypePolicy:

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the quoted computed name in the error and compare with the allowed name regex
  2. Sanitize or rename values at the IdP (e.g. use slugified group names)
  3. Adjust the binding rule template (e.g. use a literal prefix or map to a different claim)
  4. Create/verify the target ACL role or policy using exactly the computed name if it is actually valid but missing

Example fix

// before: claim yields "Platform Engineering"
BindName: "${team}"
// after: map to slug claim
BindName: "${team-slug}" // e.g. "platform-engineering"
Defensive patterns

Strategy: validation

Validate before calling

// check interpolated name against allowed charset before configuring the rule
func nameIsValid(name string) bool {
    re := regexp.MustCompile(`^[a-zA-Z0-9-_]{1,128}$`)
    return re.MatchString(name)
}

Try / catch

bindings, err := binder.Bind(log, am, identity)
if err != nil && strings.Contains(err.Error(), "is invalid") {
    log.Warn("computed bind name failed name validation", "err", err)
    return nil, ErrInvalidComputedName
}

Prevention

When it happens

Trigger: Login where the interpolated result of a binding rule's BindName is empty or contains characters outside the allowed role/policy name character set (e.g. uppercase where lowercased value is required, spaces, '@', '/' with invalid placement).

Common situations: IdP claim value contains uppercase or special characters; HIL interpolation with lowercase=false-like path yields unexpected casing; claim value empty so computed name is ""; organization names from OIDC contain spaces or slashes.

Related errors


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