hashicorp/nomad · error
namespace cannot contain template delimiters or parenthesis
Error message
namespace cannot contain template delimiters or parenthesis
What it means
The Nomad secrets template provider (nomad_provider.go) renders CT (Consul Template) snippets. validateNomadInputs rejects user-supplied namespaces that contain template delimiters '(' ')' '{' '}' so they cannot inject additional Consul Template functions or braces into the generated template. It returns 'namespace cannot contain template delimiters or parenthesis'.
Source
Thrown at client/allocrunner/taskrunner/secrets/nomad_provider.go:76
{{ range $k, $v := . }}
secret.%s.{{ $k }}={{ $v }}
{{ end }}
{{ end }}`,
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
- Remove the ( ) { } characters from the namespace value in the secrets config
- URL-encode or otherwise escape the namespace at the source system (if the provider/API supports it) instead of embedding delimiters
- Use a namespace alias/name that is plain alphanumeric plus - _ . / only
- If the namespace legitimately needs these chars, upgrade Nomad or open an issue — validation is intentionally strict to block template injection
Example fix
// before
secret {
config = { namespace = "prod(team-a)" }
}
// after
secret {
config = { namespace = "prod-team-a" }
} Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-validate the namespace before constructing the provider
func validNamespace(ns string) bool {
return ns != "" && !strings.ContainsAny(ns, "(){}")
}
// usage
if !validNamespace(cfg.Namespace) {
return errors.New("namespace 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(), "namespace cannot contain") {
return nil, fmt.Errorf("fix secrets config: namespace rejected: %w", err)
}
return nil, err
} Prevention
- Restrict namespace names to [A-Za-z0-9._-/] at creation time in the source system
- Lint Nomad job/secrets configs in CI for ( ) { } in namespace fields
- Be careful with layered templating: interpolate values before they reach the secrets block
When it happens
Trigger: Creating a Nomad secrets provider via NewNomadProvider where conf.Namespace (from the secret stanza's config) contains any of the characters ( ) { } — e.g. namespace = "prod(1)" or a name with curly braces. The check is strings.ContainsAny(conf.Namespace, "(){}") and runs before the provider is constructed.
Common situations: Copy-pasting a namespace with stray whitespace/brackets, using templated or escaped namespace strings, or intentional-but-disallowed special characters in Vault/Nomad namespace names when wiring the secrets block into a task template.
Related errors
- path 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/cb28f4935675a758.
Report an issue: GitHub.