hashicorp/nomad · error
path cannot contain template delimiters or parenthesis
Error message
path cannot contain template delimiters or parenthesis
What it means
Same guard as the namespace check in validateNomadInputs (nomad_provider.go), but applied to the secret path argument. Because the path is embedded verbatim into a generated Consul Template snippet, any ( ) { } characters could inject extra template functions; the provider therefore rejects paths containing them with 'path cannot contain template delimiters or parenthesis'.
Source
Thrown at client/allocrunner/taskrunner/secrets/nomad_provider.go:80
n.secret.Path, n.config.Namespace, n.secret.Name)
return &structs.Template{
EmbeddedTmpl: data,
DestPath: filepath.Clean(filepath.Join(n.secretDir, n.tmplFile)),
ChangeMode: structs.TemplateChangeModeNoop,
Once: true,
}
}
// validateNomadInputs ensures none of the user provided inputs contain delimiters
// that could be used to inject other CT functions.
func validateNomadInputs(conf *nomadProviderConfig, path string) error {
if strings.ContainsAny(conf.Namespace, "(){}") {
return errors.New("namespace cannot contain template delimiters or parenthesis")
}
if strings.ContainsAny(path, "(){}") {
return errors.New("path cannot contain template delimiters or parenthesis")
}
return nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Strip or replace ( ) { } from the secret path in the secrets config
- Percent-encode special characters if the backing store path uses them, per the provider's encoding rules
- Restructure the path so delimiters are not needed (use nested paths or dashes instead of parentheses)
- Verify any intermediate templating (Nomad variable interpolation) isn't leaving literal braces in the final path
Example fix
// before path = "secret/data/app(default)" // after path = "secret/data/app-default"
Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-validate the secret path before provider creation
func validSecretPath(p string) bool {
return p != "" && !strings.ContainsAny(p, "(){}")
}
// usage
if !validSecretPath(path) {
return errors.New("path must not contain ( ) { }")
} Type guard
func isDelimiterFree(s string) bool { return !strings.ContainsAny(s, "(){}") } Try / catch
p, err := NewNomadProvider(ctx, secret, dir)
if err != nil {
if strings.Contains(err.Error(), "path cannot contain") {
return nil, fmt.Errorf("rewrite secret path without delimiters: %w", err)
}
return nil, err
} Prevention
- Use dashes/underscores instead of parentheses in KV paths and URLs
- Encode special characters per provider rules instead of embedding them raw
- Add a config lint step that flags template delimiters inside path fields
When it happens
Trigger: NewNomadProvider -> validateNomadInputs(conf, path) where the path string (e.g. "secret/data/app(env)") contains any of ( ) { }. This fires when the path in the secret stanza config includes parentheses or braces, whether hand-written, templated by another layer, or copied from a URL.
Common situations: Paths pasted from URLs or docs that include parenthesized segments, paths built by string templating where surrounding braces survived interpolation, or KV paths with special characters used in Nomad variable naming conventions.
Related errors
- namespace cannot contain template delimiters or parenthesis
- secret path cannot contain template delimiters or parenthesi
- secret name cannot be empty
- secret provider cannot be empty
- secret path cannot be empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/64ff85a4bde483bb.
Report an issue: GitHub.