{"record":{"id":"f7036b960fe05d0b","repo":"grpc/grpc-go","slug":"decode-error-v","errorCode":null,"errorMessage":"decode error: %v","messagePattern":"decode error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/jwt/file_reader.go","lineNumber":98,"sourceCode":"\tif !ok { // only one period found\n\t\treturn \"\", false\n\t}\n\t_, _, ok = strings.Cut(s, tokenDelim)\n\tif ok { // three periods found\n\t\treturn \"\", false\n\t}\n\treturn claims, true\n}\n\n// extractExpiration parses the JWT token to extract the expiration time.\nfunc (r *jwtFileReader) extractExpiration(token string) (time.Time, error) {\n\tclaimsRaw, ok := extractClaimsRaw(token)\n\tif !ok {\n\t\treturn time.Time{}, fmt.Errorf(\"expected 3 parts in token\")\n\t}\n\tpayloadBytes, err := base64.RawURLEncoding.DecodeString(claimsRaw)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"decode error: %v\", err)\n\t}\n\n\tvar claims jwtClaims\n\tif err := json.Unmarshal(payloadBytes, &claims); err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"unmarshal error: %v\", err)\n\t}\n\n\tif claims.Exp == 0 {\n\t\treturn time.Time{}, fmt.Errorf(\"no expiration claims\")\n\t}\n\n\texpTime := time.Unix(claims.Exp, 0)\n\n\t// Check if token is already expired.\n\tif expTime.Before(time.Now()) {\n\t\treturn time.Time{}, fmt.Errorf(\"expired token\")\n\t}\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/jwt/file_reader.go#L80-L116","documentation":"Returned by extractExpiration when base64.RawURLEncoding.DecodeString fails on the claims segment. The header/signature split was correct (two dots present) but the payload is not valid unpadded URL-safe base64. The %v is the base64 decoder error.","triggerScenarios":"The payload segment contains characters outside the URL-safe base64 alphabet, has incorrect padding (the library uses RawURLEncoding so padding must be absent), or was corrupted/truncated.","commonSituations":"Token generated by a library that emits padded base64 (with '=') or standard base64 ('+'/'/') instead of URL-safe; manual editing of the token; encoding mismatch between issuer and gRPC jwt reader.","solutions":["Regenerate the token with a JWT library that emits unpadded URL-safe base64 (the JWT spec default).","Verify the payload segment length is a multiple of 4 after removing padding, or that it has no '='.","Replace any '+'/'/' characters and strip '=' to test whether encoding is the cause."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func claimsDecode(claimsSeg string) ([]byte, error) {\n    // Mirror the reader: RawURLEncoding (no padding).\n    return base64.RawURLEncoding.DecodeString(claimsSeg)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Issue tokens with a standard JWT library that emits unpadded URL-safe base64.","Reject tokens containing '=' padding or '+'/'/' characters at ingestion time.","Log the failing segment length to spot truncation."],"tags":["grpc","jwt","base64","parsing","validation"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}