hashicorp/nomad · error
require only one of PemKey or PemKeyFile
Error message
require only one of PemKey or PemKeyFile
What it means
Nomad's OIDCClientAssertionKey.Validate() requires the private key for a client assertion to be supplied in exactly one way: inline via PemKey or via a file path with PemKeyFile. This sentinel error (ErrAmbiguousClientAssertionKey) is returned when both fields are set, because the library cannot tell which source is authoritative.
Source
Thrown at nomad/structs/acl.go:1839
}
func (k *OIDCClientAssertionKey) Canonicalize() {
if k == nil {
return
}
if k.KeyIDHeader == "" {
if k.KeyID != "" {
k.KeyIDHeader = OIDCClientAssertionHeaderKid
}
if k.PemCert != "" || k.PemCertFile != "" {
k.KeyIDHeader = OIDCClientAssertionHeaderX5tS256
}
}
}
var (
ErrMissingClientAssertionKey = errors.New("missing PemKey or PemKeyFile")
ErrAmbiguousClientAssertionKey = errors.New("require only one of PemKey or PemKeyFile")
ErrMissingClientAssertionKeyID = errors.New("missing PemCert, PemCertFile, or KeyID")
ErrAmbiguousClientAssertionKeyID = errors.New("require only one of PemCert, PemCertFile, or KeyID")
ErrInvalidClientAssertionKeyPath = errors.New("invalid PemKeyFile")
ErrInvalidClientAssertionCertPath = errors.New("invalid PemCertFile")
ErrInvalidKeyIDHeader = errors.New("invalid KeyIDHeader")
)
// Validate ensures that one Key and one Cert or KeyID are provided,
// and that the key ID header is valid for the provided KeyID or cert.
func (k *OIDCClientAssertionKey) Validate() error {
if k == nil {
return nil
}
// mutually exclusive key fields
// must have key file or base64, but not both
if k.PemKey == "" && k.PemKeyFile == "" {
return ErrMissingClientAssertionKeyView on GitHub (pinned to 482b49bf1a)
Solutions
- Remove either the PemKey inline value or the PemKeyFile path so exactly one is set
- Keep PemKeyFile for production (secret stays on disk) and clear PemKey
- Keep PemKey for in-memory/template-injected setups and clear PemKeyFile
Example fix
// before
key := &structs.OIDCClientAssertionKey{
PemKey: string(pemBytes),
PemKeyFile: "/etc/nomad/tls/client.key",
}
// after
key := &structs.OIDCClientAssertionKey{
PemKeyFile: "/etc/nomad/tls/client.key",
} Defensive patterns
Strategy: validation
Validate before calling
if key.PemKey != "" && key.PemKeyFile != "" {
// drop one before calling Validate()
key.PemKey = ""
}
if err := key.Validate(); err != nil { return err } Try / catch
if err := key.Validate(); err != nil {
if errors.Is(err, structs.ErrAmbiguousClientAssertionKey) {
// fix config: keep exactly one of PemKey / PemKeyFile
}
return err
} Prevention
- Configure exactly one key source per environment; drive it from a single template variable
- Prefer PemKeyFile in production so secrets live on disk
- Run key.Validate() in unit tests over all rendered configs
When it happens
Trigger: Calling Validate() (directly or via ACLAuthMethod upsert/validation endpoints) on an OIDCClientAssertionKey where both PemKey != "" and PemKeyFile != "".
Common situations: Config templates or HCL/JSON job files where an operator pasted both an inline PEM block and a path; tooling that renders both fields from a vault/secret reference; copy-paste from examples that show both options.
Related errors
- missing PemCert, PemCertFile, or KeyID
- require only one of PemCert, PemCertFile, or KeyID
- invalid PemKeyFile
- invalid PemCertFile
- invalid KeyIDHeader
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/465a454e90e564b1.
Report an issue: GitHub.