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

  1. Set exactly one of PemKey (PEM contents) or PemKeyFile (path) on the key config — not both, which yields ErrAmbiguousClientAssertionKey
  2. 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

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


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