{"record":{"id":"1510914f4c878d35","repo":"hashicorp/nomad","slug":"error-reading-s-w","errorCode":null,"errorMessage":"error reading %s: %w","messagePattern":"error reading (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/oidc/client_assertion.go","lineNumber":128,"sourceCode":"\t\treturn cass.NewJWTWithRSAKey(clientID, as.Audience, algo, rsaKey, opts...)\n\n\tdefault: // this shouldn't happen, but just in case\n\t\treturn nil, fmt.Errorf(\"unknown OIDC KeySource %q\", as.KeySource)\n\t}\n}\n\n// getCassPrivateKey parses the structs.OIDCClientAssertionKey PemKeyFile\n// or PemKey, depending on which is set.\nfunc getCassPrivateKey(k *structs.OIDCClientAssertionKey) (key *rsa.PrivateKey, err error) {\n\tvar bts []byte\n\tvar source string // for informative error messages\n\n\t// pem file on disk\n\tif k.PemKeyFile != \"\" {\n\t\tsource = \"PemKeyFile\"\n\t\tbts, err = os.ReadFile(k.PemKeyFile)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading %s: %w\", source, err)\n\t\t}\n\t}\n\t// or pem string\n\tif k.PemKey != \"\" {\n\t\tsource = \"PemKey\"\n\t\tbts = []byte(k.PemKey)\n\t}\n\n\t// ensure newlines around pem header/footer\n\tbts = newlineHeaders(bts)\n\n\tkey, err = gojwt.ParseRSAPrivateKeyFromPEM(bts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing %s: %w\", source, err)\n\t}\n\tif err := key.Validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"error validating %s: %w\", source, err)\n\t}","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/oidc/client_assertion.go#L110-L146","documentation":"Fires in getCassPrivateKey when os.ReadFile fails on the OIDC client assertion's configured PemKeyFile — the file path is wrong, missing, or unreadable, so the private key for the client assertion JWT cannot be loaded.","triggerScenarios":"BuildClientAssertionJWT → getCassPrivateKey when OIDCClientAssertionKey.PemKeyFile is set and the file cannot be read (missing path, wrong permissions, unreadable volume).","commonSituations":"Path typo or relative path that doesn't resolve on Nomad servers; file only mounted on clients, not servers; permissions preventing the nomad user from reading; secret not provisioned by the deployment tool.","solutions":["Verify the PemKeyFile path exists on every Nomad server and is readable: `ls -l <path> && sudo -u nomad cat <path>`.","Use an absolute path and ensure the key is provisioned/templated (e.g. Vault agent, volume mount) on server nodes.","Alternatively embed the key inline via PemKey instead of a file path."],"exampleFix":"// before\nkey := &structs.OIDCClientAssertionKey{PemKeyFile: \"client.key\"}\n// after\nkey := &structs.OIDCClientAssertionKey{PemKeyFile: \"/etc/nomad.d/tls/oidc-client.key\"}","handlingStrategy":"validation","validationCode":"if k.PemKeyFile != \"\" {\n  if _, err := os.ReadFile(k.PemKeyFile); err != nil {\n    return fmt.Errorf(\"PemKeyFile unreadable before assertion build: %w\", err)\n  }\n}","typeGuard":null,"tryCatchPattern":"key, err := getCassPrivateKey(k)\nif err != nil && strings.Contains(err.Error(), \"error reading\") {\n  return fmt.Errorf(\"check PemKeyFile path/permissions on Nomad servers: %w\", err)\n}","preventionTips":["Use absolute paths and provision key files on all server nodes.","Check file ownership/permissions (readable by the nomad user) after provisioning.","Prefer inline PemKey when file distribution is unreliable."],"tags":["oidc","client-assertion","file-io","filesystem"],"backgroundTag":"file-not-found","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}