{"record":{"id":"2eafd600d5ecddac","repo":"grpc/grpc-go","slug":"token-file-access-error","errorCode":null,"errorMessage":"token file access error","messagePattern":"token file access error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/jwt/file_reader.go","lineNumber":32,"sourceCode":" * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage jwt\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar (\n\terrTokenFileAccess = errors.New(\"token file access error\")\n\terrJWTValidation   = errors.New(\"invalid JWT\")\n)\n\n// jwtClaims represents the JWT claims structure for extracting expiration time.\ntype jwtClaims struct {\n\tExp int64 `json:\"exp\"`\n}\n\n// jwtFileReader handles reading and parsing JWT tokens from files.\n// It is safe to call methods on this type concurrently as no state is stored.\ntype jwtFileReader struct {\n\ttokenFilePath string\n}\n\n// readToken reads and parses a JWT token from the configured file.\n// Returns the token string, expiration time, and any error encountered.\nfunc (r *jwtFileReader) readToken() (string, time.Time, error) {\n\ttokenBytes, err := os.ReadFile(r.tokenFilePath)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/jwt/file_reader.go#L14-L50","documentation":"errTokenFileAccess is the sentinel error returned by the JWT file reader when os.ReadFile fails on the configured token file path. The actual OS-level error (permission denied, file not found, etc.) is wrapped inside, so callers can unwrap it to diagnose the filesystem problem. This is used by JWT-based per-RPC credentials that read a token (and its expiration) from a file on every RPC or on refresh.","triggerScenarios":"The jwtFileReader.readToken method calls os.ReadFile(r.tokenFilePath) and it fails. Common failure causes: the path is wrong, the file does not exist, the process lacks read permission, or the path points to a directory. Also triggered when a mounted secret volume (e.g., Kubernetes service-account token) is not yet available.","commonSituations":"Kubernetes pods where the projected service-account token path changed or the volume mount is delayed. Containers running as a user without read access to the token file. Configuration typos in the token file path (absolute vs relative). Rotating-token setups where the file is briefly absent during rotation.","solutions":["Verify the token file path is absolute and correct; check it exists with ls -l from the same process context.","Ensure the process user has read permission on the file (chmod/chown, or runAsUser in Kubernetes).","If using Kubernetes projected tokens, confirm the volumeMount and volume are configured and the pod has started successfully.","Unwrap the error with errors.Unwrap or fmt.Errorf(%w) logging to see the underlying OS error."],"exampleFix":"// before\ntokenPath := \"/var/run/secrets/token\" // wrong path or missing mount\nreader := newJWTFileReader(tokenPath)\n// after\ntokenPath := \"/var/run/secrets/tokens/gcp-sa-token\" // verified path\n// also ensure Kubernetes volumeMount is present:\n// volumeMounts:\n// - name: token\n//   mountPath: /var/run/secrets/tokens\n//   readOnly: true","handlingStrategy":"try-catch","validationCode":"// Check file exists and is readable before creating the credential:\nif info, err := os.Stat(tokenPath); err != nil || info.IsDir() {\n    return fmt.Errorf(\"token file %q not accessible: %w\", tokenPath, err)\n}","typeGuard":null,"tryCatchPattern":"token, exp, err := reader.readToken()\nif err != nil {\n    if errors.Is(err, errTokenFileAccess) {\n        // log underlying OS error, alert ops team\n    }\n    return err\n}","preventionTips":["Use absolute paths for token files.","Verify file permissions (readable by the process user) at startup.","In Kubernetes, ensure projected token volumes are mounted before the process reads them.","Log the wrapped OS error for diagnosis."],"tags":["go","grpc","jwt","credentials","filesystem"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}