{"record":{"id":"b6d34b794819c032","repo":"grpc/grpc-go","slug":"tokenfilepath-cannot-be-empty","errorCode":null,"errorMessage":"tokenFilePath cannot be empty","messagePattern":"tokenFilePath cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/jwt/token_file_call_creds.go","lineNumber":57,"sourceCode":"type jwtTokenFileCallCreds struct {\n\tfileReader      *jwtFileReader\n\tbackoffStrategy backoff.Strategy\n\n\t// cached data protected by mu\n\tmu               sync.Mutex\n\tcachedAuthHeader string    // \"Bearer \" + token\n\tcachedExpiry     time.Time // Slightly less than actual expiration time\n\tcachedError      error     // Error from last failed attempt\n\tretryAttempt     int       // Current retry attempt number\n\tnextRetryTime    time.Time // When next retry is allowed\n\tpendingRefresh   bool      // Whether a refresh is currently in progress\n}\n\n// NewTokenFileCallCredentials creates PerRPCCredentials that reads JWT tokens\n// from the specified file path.\nfunc NewTokenFileCallCredentials(tokenFilePath string) (credentials.PerRPCCredentials, error) {\n\tif tokenFilePath == \"\" {\n\t\treturn nil, fmt.Errorf(\"tokenFilePath cannot be empty\")\n\t}\n\n\tcreds := &jwtTokenFileCallCreds{\n\t\tfileReader:      &jwtFileReader{tokenFilePath: tokenFilePath},\n\t\tbackoffStrategy: backoff.DefaultExponential,\n\t}\n\n\treturn creds, nil\n}\n\n// GetRequestMetadata gets the current request metadata, refreshing tokens if\n// required. This implementation follows the PerRPCCredentials interface.  The\n// tokens will get automatically refreshed if they are about to expire or if\n// they haven't been loaded successfully yet.\n// If it's not possible to extract a token from the file, UNAVAILABLE is\n// returned.\n// If the token is extracted but invalid, then UNAUTHENTICATED is returned.\n// If errors are encoutered, a backoff is applied before retrying.","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/jwt/token_file_call_creds.go#L39-L75","documentation":"Thrown by jwt.NewTokenFileCallCredentials when the supplied tokenFilePath argument is the empty string (token_file_call_creds.go:57). The JWT-from-file call-credentials implementation (gRFC A97) needs a concrete filesystem path to read and refresh Bearer tokens from, so an empty path cannot produce a usable credential. It is a construction-time programmer error, not a runtime transport failure.","triggerScenarios":"Calling jwt.NewTokenFileCallCredentials(\"\") directly, or passing an unset/zero-value string variable (e.g. an env var like os.Getenv(\"JWT_TOKEN_FILE\") that was never exported, or a struct field left as its default) into the constructor.","commonSituations":"Deployment env where the JWT token-file path is injected via an env var or secret mount that is missing/misspelled; tests that forget to set the path; config loaders that swallow the missing-key case and return \"\" instead of failing.","solutions":["Pass a non-empty, absolute path to a readable file when calling NewTokenFileCallCredentials.","Validate the config source (env var / flag) for emptiness and fail fast at startup with a clear message.","If the path comes from a secret mount, confirm the volume/secret is mounted and the path key is correct."],"exampleFix":"// before\ncreds, err := jwt.NewTokenFileCallCredentials(os.Getenv(\"JWT_TOKEN_FILE\"))\n\n// after\npath := os.Getenv(\"JWT_TOKEN_FILE\")\nif path == \"\" {\n    log.Fatal(\"JWT_TOKEN_FILE must be set\")\n}\ncreds, err := jwt.NewTokenFileCallCredentials(path)","handlingStrategy":"validation","validationCode":"path := os.Getenv(\"JWT_TOKEN_FILE\")\nif strings.TrimSpace(path) == \"\" {\n    log.Fatal(\"JWT_TOKEN_FILE must be a non-empty file path\")\n}\nif _, err := os.Stat(path); err != nil {\n    log.Fatalf(\"token file not accessible: %v\", err)\n}\ncreds, err := jwt.NewTokenFileCallCredentials(path)\nif err != nil { log.Fatal(err) }","typeGuard":"// PerRPCCredentials must be non-nil and transport-secure; guard at construction:\nfunc mustJWTCallCreds(path string) credentials.PerRPCCredentials {\n    if path == \"\" { panic(\"empty tokenFilePath\") }\n    c, err := jwt.NewTokenFileCallCredentials(path)\n    if err != nil { panic(err) }\n    return c\n}","tryCatchPattern":null,"preventionTips":["Resolve all credential file paths from config at startup and fail fast on empty/missing values.","Use absolute paths for token files and verify readability before dialing.","Unit-test credential construction with the real config object to catch empty-string fields."],"tags":["jwt","validation","configuration","go","call-credentials"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}