hashicorp/nomad · error
missing PemKey or PemKeyFile
Error message
missing PemKey or PemKeyFile
What it means
For private_key client assertions, the signing key must be supplied either inline (PemKey) or via a file path (PemKeyFile). The exported sentinel error ErrMissingClientAssertionKey is returned by the key Validate when both are empty.
Source
Thrown at nomad/structs/acl.go:1838
return n
}
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 == "" {View on GitHub (pinned to 482b49bf1a)
Solutions
- Set exactly one of PemKey (PEM contents) or PemKeyFile (path) on the key config — not both, which yields ErrAmbiguousClientAssertionKey
- Verify the file path exists and is readable by the Nomad agent if using PemKeyFile
Example fix
// before
key := &api.OIDCClientAssertionKey{KeyID: "key-1"}
// after
key := &api.OIDCClientAssertionKey{KeyID: "key-1", PemKeyFile: "/etc/nomad/assertion.key"} Defensive patterns
Strategy: validation
Validate before calling
func assertionKeyOK(k *structs.OIDCClientAssertionKey) error {
if k == nil || (k.PemKey == "" && k.PemKeyFile == "") {
return structs.ErrMissingClientAssertionKey
}
if k.PemKey != "" && k.PemKeyFile != "" {
return structs.ErrAmbiguousClientAssertionKey
}
return nil
} Try / catch
if err := key.Validate(); err != nil {
switch {
case errors.Is(err, structs.ErrMissingClientAssertionKey):
// set PemKey or PemKeyFile and retry submission
case errors.Is(err, structs.ErrAmbiguousClientAssertionKey):
// keep only one of PemKey/PemKeyFile
}
} Prevention
- Supply exactly one of PemKey/PemKeyFile
- Check file existence/permissions when using PemKeyFile
- Reuse the library's sentinel errors with errors.Is for branching
When it happens
Trigger: Submitting an OIDCClientAssertionKey with both PemKey and PemKeyFile empty (e.g. only KeyID/KeyIDHeader set) during auth method validation.
Common situations: Configuring only the key ID and header metadata assuming the key is fetched elsewhere; mounting failures where the file path was configured but the code path reads PemKey first; hand-written JSON omitting both key fields.
Related errors
- missing OIDCDiscoveryURL
- missing OIDCClientID
- missing Audience
- PrivateKey is required for `private_key` KeySource
- OIDCClientSecret is required for `client_secret` KeySource
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e0ddf021658ea919.
Report an issue: GitHub.