{"record":{"id":"601753bba6934d4f","repo":"hashicorp/nomad","slug":"failed-to-serialize-client-assertion-jwt-w","errorCode":null,"errorMessage":"failed to serialize client_assertion jwt: %w","messagePattern":"failed to serialize client_assertion jwt: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/acl_endpoint.go","lineNumber":3181,"sourceCode":"\t// KeySource = \"nomad\", but we get it here to avoid exposing more of the\n\t// codebase to the encrypter.\n\tnomadKey, nomadKID, err := a.srv.encrypter.GetActiveKey()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get active nomad key: %w\", err)\n\t}\n\tj, err := oidc.BuildClientAssertionJWT(config, nomadKey, nomadKID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to build client_assertion jwt: %w\", err)\n\t}\n\tif config.VerboseLogging {\n\t\t// a user initially setting up the auth method, as one might with\n\t\t// VerboseLogging enabled, may benefit from not having to do a full\n\t\t// login flow to see the jwt (and any possible Serialize() error).\n\t\t// we say \"example\" in the log, because the cap library will run\n\t\t// Serialize() again internally, so it won't use this same jwt.\n\t\ttoken, err := j.Serialize()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to serialize client_assertion jwt: %w\", err)\n\t\t}\n\t\ta.logger.Debug(\"example client_assertion\", \"oidc_client_id\", config.OIDCClientID, \"jwt\", token)\n\t}\n\treturn j, nil\n}\n\nfunc (a *ACL) CreateClientIntroductionToken(\n\targs *structs.ACLCreateClientIntroductionTokenRequest,\n\treply *structs.ACLCreateClientIntroductionTokenResponse) error {\n\n\tauthErr := a.srv.Authenticate(a.ctx, args)\n\n\tif done, err := a.srv.forward(structs.ACLCreateClientIntroductionTokenRPCMethod, args, args, reply); done {\n\t\treturn err\n\t}\n\ta.srv.MeasureRPCRate(\"acl\", structs.RateMetricWrite, args)\n\n\t// This endpoint can only be used once all servers in the local region have","sourceCodeStart":3163,"sourceCodeEnd":3199,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/acl_endpoint.go#L3163-L3199","documentation":"Thrown by oidcClientAssertion when j.Serialize() fails while rendering the built client_assertion JWT (only when config.VerboseLogging is enabled, for a debug log). Serialize re-signs/encodes the JWT; failure means the JWS cannot be produced even though the JWT object was constructed — usually key/algorithm incompatibility surfacing at signing time.","triggerScenarios":"config.VerboseLogging is true and j.Serialize() errors on the example JWT inside oidcClientAssertion, which is called by UpsertAuthMethods and oidcRequest.","commonSituations":"Same key/algorithm mismatch as jwt build errors but detected at serialization, corrupted key material, or a cap library serialization bug — only visible to users who enable VerboseLogging on the auth method.","solutions":["Read the wrapped cause; fix the key/algorithm mismatch in OIDCClientAssertion (SigningAlgorithm vs actual key type).","Verify the private key PEM (KeySource=private-key) is valid and unencrypted, or that the nomad keyring key is healthy.","Disable VerboseLogging to unblock the flow if it only fails on this debug path, then report the underlying serialization issue upstream.","Upgrade Nomad / cap library if serialization is failing on a valid configuration."],"exampleFix":"// before: verbose logging with mismatched algorithm\n\"OIDCClientAssertion\": { \"KeySource\": \"nomad\", \"SigningAlgorithm\": \"ES256\" }, \"VerboseLogging\": true\n// after: algorithm that matches available keys\n\"OIDCClientAssertion\": { \"KeySource\": \"nomad\", \"SigningAlgorithm\": \"RS256\" }, \"VerboseLogging\": true","handlingStrategy":"try-catch","validationCode":"// preflight: same key/algorithm validation as build step, plus verbose-logging awareness\nif cfg.VerboseLogging && cfg.OIDCClientAssertion.KeySource == \"private-key\" {\n  if _, err := jwtSignedParser(cfg.OIDCClientAssertion.PrivateKey, cfg.OIDCClientAssertion.SigningAlgorithm); err != nil {\n    return err\n  }\n}","typeGuard":null,"tryCatchPattern":"token, err := j.Serialize()\nif err != nil {\n    return nil, fmt.Errorf(\"failed to serialize client_assertion jwt: %w\", err)\n}","preventionTips":["Fix key/algorithm mismatches rather than just disabling VerboseLogging.","Validate key material offline before UpsertAuthMethods.","Report persistent serialization failures on valid configs upstream."],"tags":["jwt","serialization","oidc","client-assertion","nomad"],"backgroundTag":"jwt-serialization-failed","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"}