hashicorp/nomad · error
attribute %q is missing an opening brace
Error message
attribute %q is missing an opening brace
What it means
This error comes from Nomad's constraint attribute validation (validateConstraintAttribute). Constraint targets can be an attribute path or an interpolation expression. If a target starts with '$' but is not exactly '${...}', the opening brace is missing, so the constraint is rejected. It exists to catch malformed interpolation syntax early at job validation time.
Source
Thrown at nomad/structs/constraint.go:44
"${device.",
"${meta.",
}
)
// validateConstraintAttribute ensures the constraint attribute is valid. It
// does this by ensuring any interpolated field can be handled by the
// resolveTarget function.
func validateConstraintAttribute(target string) error {
// If no prefix delimieter is included, we assume this is a literal value
// and is therefore valid.
if !strings.HasPrefix(target, "$") {
return nil
}
// Must have the correct opening and closing delimeters.
if !strings.HasPrefix(target, "${") {
return fmt.Errorf("attribute %q is missing an opening brace", target)
}
if !strings.HasSuffix(target, "}") {
return fmt.Errorf("attribute %q is missing a closing brace", target)
}
// Perform our exact target matching first. If the target does not hit this
// exact match, we will fall through to the prefix match check.
if slices.Contains(validConstraintExactTargets, target) {
return nil
}
// Check the target against our valid prefixes.
for _, prefix := range validConstraintPrefixTargets {
if strings.HasPrefix(target, prefix) {
return nil
}
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Wrap the variable name in braces: change "$node.class" to "${node.class}".
- If you meant an exact target, use one of the valid literal targets (e.g. "${node.unique.id}") with full ${...} syntax.
- Run nomad job validate locally to catch the malformed attribute before submitting.
Example fix
// before
constraint {
attribute = "$node.class"
operator = "="
value = "linux"
}
// after
constraint {
attribute = "${node.class}"
operator = "="
value = "linux"
} Defensive patterns
Strategy: validation
Validate before calling
func validConstraintTarget(target string) bool {
if !strings.HasPrefix(target, "$") { return true }
return strings.HasPrefix(target, "${") && strings.HasSuffix(target, "}")
} Prevention
- Always use full ${...} interpolation syntax for constraint attributes.
- Run `nomad job validate` in CI before submitting job specs.
- Lint HCL templates for unbalanced braces on '$' expressions.
When it happens
Trigger: Registering or validating a job whose constraint 'attribute' field starts with '$' but not '${', e.g. attribute="$node.class" or attribute="$attr" instead of "${node.class}" / "${attr...}".
Common situations: Hand-written job specs where the author forgot the opening brace after '$'; typos when converting from older HCL interpolation styles; copy-paste errors dropping '{'.
Related errors
- attribute %q is missing a closing brace
- Missing constraint operand
- no attribute provided but is required by operator
- invalid constraint: %v
- unsupported attribute %q
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/c1aeb959bfa82562.
Report an issue: GitHub.