hashicorp/nomad · error
attribute %q is missing a closing brace
Error message
attribute %q is missing a closing brace
What it means
validateConstraintAttribute requires constraint targets using interpolation to have both opening and closing delimiters: ${...}. This error fires when the target starts with '${' but does not end with '}'. It prevents partially-formed interpolation expressions from reaching scheduler evaluation.
Source
Thrown at nomad/structs/constraint.go:47
)
// 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
}
}
// If we have reached this point, the target has not matched any valid
// options. Return an error that includes the target string, so it is
// immediately clear what constraint failed as job specifications canView on GitHub (pinned to 482b49bf1a)
Solutions
- Append the missing '}' so the attribute is a complete ${...} expression.
- Verify the whole attribute string with nomad job validate before submitting.
- If the value was intended as a literal (non-interpolated) name, remove the '$' prefix entirely.
Example fix
// before
constraint {
attribute = "${attr.kernel.version"
operator = ">="
value = "5.4"
}
// after
constraint {
attribute = "${attr.kernel.version}"
operator = ">="
value = "5.4"
} Defensive patterns
Strategy: validation
Validate before calling
if !strings.HasSuffix(strings.TrimSuffix(attr, "}"), "}") {
return fmt.Errorf("constraint attribute %q not a complete ${...} expression", attr)
} Prevention
- Pair every '${' with a '}' in attribute fields; editors with bracket matching help.
- Avoid templating tools that may strip trailing braces; escape as needed.
- Validate job specs with nomad job validate before apply.
When it happens
Trigger: A job constraint attribute like "${node.class" or "${attr.network.speed" that opens the interpolation but never closes it with '}'.
Common situations: Truncated lines from copy-paste; editors or templating systems stripping the closing brace; typos when hand-editing job files.
Related errors
- attribute %q is missing an opening 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/04bab5902faba544.
Report an issue: GitHub.