{"record":{"id":"f4523db77648af7c","repo":"grpc/grpc-go","slug":"failed-to-create-jwt-call-credentials-v","errorCode":null,"errorMessage":"failed to create JWT call credentials: %v","messagePattern":"failed to create JWT call credentials: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/bootstrap/jwtcreds/call_creds.go","lineNumber":51,"sourceCode":"// config must match the structure specified in gRFC A97.\n//\n// The caller is expected to invoke the cancel function when they are done using\n// the returned call creds. This cancel function is idempotent.\nfunc NewCallCredentials(configJSON json.RawMessage) (c credentials.PerRPCCredentials, cancel func(), err error) {\n\tvar cfg struct {\n\t\tJWTTokenFile string `json:\"jwt_token_file\"`\n\t}\n\temptyFn := func() {}\n\n\tif err := json.Unmarshal(configJSON, &cfg); err != nil {\n\t\treturn nil, emptyFn, fmt.Errorf(\"failed to unmarshal JWT call credentials config: %v\", err)\n\t}\n\tif cfg.JWTTokenFile == \"\" {\n\t\treturn nil, emptyFn, fmt.Errorf(\"jwt_token_file is required in JWT call credentials config\")\n\t}\n\tcallCreds, err := jwt.NewTokenFileCallCredentials(cfg.JWTTokenFile)\n\tif err != nil {\n\t\treturn nil, emptyFn, fmt.Errorf(\"failed to create JWT call credentials: %v\", err)\n\t}\n\treturn callCreds, emptyFn, nil\n}\n","sourceCodeStart":33,"sourceCodeEnd":55,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/bootstrap/jwtcreds/call_creds.go#L33-L55","documentation":"Returned by jwtcreds.NewCallCredentials when jwt.NewTokenFileCallCredentials fails for the supplied file path. The underlying error from the JWT package is wrapped.","triggerScenarios":"Triggered at call_creds.go:51 when jwt.NewTokenFileCallCredentials(cfg.JWTTokenFile) errors. Typically the file cannot be read or cannot be parsed.","commonSituations":"Token file does not exist at the given path; permission denied; file is empty or not a valid JWT (wrong number of segments, bad base64); path is correct in dev but not mounted in the container.","solutions":["Verify the path exists and is readable: ls -l /var/secrets/token.jwt.","Inspect the underlying %v error to distinguish missing-file vs parse failure.","Confirm the file contents is a valid compact-serialization JWT (three base64url segments separated by '.').","In containers, ensure the secret holding the token is mounted at that path."],"exampleFix":"# before: file missing or unreadable\n{\"jwt_token_file\":\"/var/secrets/token.jwt\"}\n# ls /var/secrets/token.jwt -> No such file\n\n# after: create/mount the token\necho -n 'eyJhbGciOi...signature' > /var/secrets/token.jwt\nchmod 600 /var/secrets/token.jwt","handlingStrategy":"validation","validationCode":"// Pre-flight check of the JWT token file before bootstrap.\nfunc checkJWTTokenFile(path string) error {\n    fi, err := os.Stat(path)\n    if err != nil {\n        return fmt.Errorf(\"jwt token file: %w\", err)\n    }\n    if fi.Size() == 0 {\n        return fmt.Errorf(\"jwt token file is empty\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if _, _, err := jwtcreds.NewCallCredentials(cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to create JWT call credentials\") {\n        // verify file exists/permissions/contents, then retry.\n    }\n}","preventionTips":["Mount the JWT token as a secret at a fixed path.","Add a startup check that the token file is non-empty.","Refresh rotated tokens via a mounted secret, not a one-shot copy."],"tags":["grpc","xds","jwt","call-credentials","filesystem","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}