hashicorp/nomad · error
invalid PemCertFile
Error message
invalid PemCertFile
What it means
Like the key path, PemCertFile must be an absolute path. ErrInvalidClientAssertionCertPath is wrapped with 'must be absolute; got: <path>' because the certificate file must be readable by Nomad agents regardless of their working directory.
Source
Thrown at nomad/structs/acl.go:1843
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 ErrMissingClientAssertionKey
}
if k.PemKey != "" && k.PemKeyFile != "" {
return ErrAmbiguousClientAssertionKey
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Use an absolute path such as /etc/nomad/tls/client.crt
- Resolve the path at deploy time (filepath.Abs / abspath) before writing config
- Ensure the file exists and is readable by the Nomad agent user
Example fix
// before
key := &structs.OIDCClientAssertionKey{
PemCertFile: "./who-knows-where-this-might-be.cert",
}
// after
key := &structs.OIDCClientAssertionKey{
PemCertFile: "/etc/nomad/tls/client.cert",
} Defensive patterns
Strategy: validation
Validate before calling
if key.PemCertFile != "" && !path.IsAbs(key.PemCertFile) {
abs, err := filepath.Abs(key.PemCertFile)
if err != nil { return err }
key.PemCertFile = abs
} Try / catch
if err := key.Validate(); err != nil {
if strings.Contains(err.Error(), structs.ErrInvalidClientAssertionCertPath.Error()) {
// replace with absolute cert path and re-validate
}
return err
} Prevention
- Keep certs under a fixed absolute directory like /etc/nomad/tls/
- Expand ~ and relative refs at deploy time
- Check file existence and permissions along with absoluteness
When it happens
Trigger: Validate() where k.PemCertFile != "" and !path.IsAbs(k.PemCertFile), e.g. "./who-knows-where-this-might-be.cert".
Common situations: Relative or ~ paths in auth-method config; CI pipelines that resolve certs relative to the repo; operators copying paths from docs examples.
Related errors
- invalid PemKeyFile
- require only one of PemKey or PemKeyFile
- missing PemCert, PemCertFile, or KeyID
- require only one of PemCert, PemCertFile, or KeyID
- invalid KeyIDHeader
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3a300eca37dac513.
Report an issue: GitHub.