grpc/grpc-go · error

tokenFilePath cannot be empty

Error message

tokenFilePath cannot be empty

What it means

Returned by NewTokenFileCallCredentials when tokenFilePath is the empty string. This is a pure programming error: the constructor refuses to create a credential that could never read a token. No I/O is attempted.

Solutions

  1. Pass a non-empty absolute path to NewTokenFileCallCredentials.
  2. Validate the configured path at startup and fail fast with a clear message if empty.
  3. Set the missing environment variable (e.g. TOKEN_FILE) in the container/pod spec.

Example fix

// before
creds, err := jwt.NewTokenFileCallCredentials(os.Getenv("TOKEN_FILE"))
// after
path := os.Getenv("TOKEN_FILE")
if path == "" {
    log.Fatal("TOKEN_FILE env var is required")
}
creds, err := jwt.NewTokenFileCallCredentials(path)
Defensive patterns

Strategy: validation

Validate before calling

if tokenFilePath == "" {
    log.Fatal("tokenFilePath is required")
}
creds, err := jwt.NewTokenFileCallCredentials(tokenFilePath)

Type guard

func nonEmptyPath(p string) bool { return strings.TrimSpace(p) != "" }

Prevention

When it happens

Trigger: Passing an unset struct field, empty env var, or zero-value string to NewTokenFileCallCredentials; a config load that silently defaulted the path to "".

Common situations: Missing TOKEN_FILE env var in the deployment; config YAML field misnamed so it deserializes to empty; refactoring that dropped the path argument.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/b6d34b794819c032. Report an issue: GitHub.

Appendix: source

Thrown at credentials/jwt/token_file_call_creds.go:57

type jwtTokenFileCallCreds struct {
	fileReader      *jwtFileReader
	backoffStrategy backoff.Strategy

	// cached data protected by mu
	mu               sync.Mutex
	cachedAuthHeader string    // "Bearer " + token
	cachedExpiry     time.Time // Slightly less than actual expiration time
	cachedError      error     // Error from last failed attempt
	retryAttempt     int       // Current retry attempt number
	nextRetryTime    time.Time // When next retry is allowed
	pendingRefresh   bool      // Whether a refresh is currently in progress
}

// NewTokenFileCallCredentials creates PerRPCCredentials that reads JWT tokens
// from the specified file path.
func NewTokenFileCallCredentials(tokenFilePath string) (credentials.PerRPCCredentials, error) {
	if tokenFilePath == "" {
		return nil, fmt.Errorf("tokenFilePath cannot be empty")
	}

	creds := &jwtTokenFileCallCreds{
		fileReader:      &jwtFileReader{tokenFilePath: tokenFilePath},
		backoffStrategy: backoff.DefaultExponential,
	}

	return creds, nil
}

// GetRequestMetadata gets the current request metadata, refreshing tokens if
// required. This implementation follows the PerRPCCredentials interface.  The
// tokens will get automatically refreshed if they are about to expire or if
// they haven't been loaded successfully yet.
// If it's not possible to extract a token from the file, UNAVAILABLE is
// returned.
// If the token is extracted but invalid, then UNAUTHENTICATED is returned.
// If errors are encoutered, a backoff is applied before retrying.

View on GitHub (pinned to 0c51461d27)