hashicorp/nomad · error

missing PemCert, PemCertFile, or KeyID

Error message

missing PemCert, PemCertFile, or KeyID

What it means

An OIDC client assertion needs a way to identify the signing key: either an inline certificate (PemCert), a certificate file (PemCertFile), or a precomputed key ID (KeyID). ErrMissingClientAssertionKeyID is returned when none of the three is provided, so the JWT 'kid'/x5t header could not be derived.

Source

Thrown at nomad/structs/acl.go:1840

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 ErrMissingClientAssertionKey
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set PemCertFile to the absolute path of the certificate matching the private key
  2. Or set PemCert to the inline PEM certificate
  3. Or set KeyID plus KeyIDHeader (KeyID requires KeyIDHeader "kid")

Example fix

// before
key := &structs.OIDCClientAssertionKey{
  PemKeyFile: "/etc/nomad/tls/client.key",
}
// after
key := &structs.OIDCClientAssertionKey{
  PemKeyFile: "/etc/nomad/tls/client.key",
  PemCertFile: "/etc/nomad/tls/client.crt",
}
Defensive patterns

Strategy: validation

Validate before calling

if key.PemCert == "" && key.PemCertFile == "" && key.KeyID == "" {
    return fmt.Errorf("client assertion needs PemCert, PemCertFile, or KeyID")
}
if err := key.Validate(); err != nil { return err }

Try / catch

if err := key.Validate(); err != nil {
    if errors.Is(err, structs.ErrMissingClientAssertionKeyID) {
        // add a cert or KeyID before applying
    }
    return err
}

Prevention

When it happens

Trigger: Validate() on an OIDCClientAssertionKey where PemCert == "" && PemCertFile == "" && KeyID == "".

Common situations: Operator configured only the private key (PemKey/PemKeyFile) but forgot the matching certificate or key ID; partial migration of auth-method config; copying a key-only example.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/db69ee955381785e. Report an issue: GitHub.