jaegertracing/jaeger · error
failed to read token file: %w
Error message
failed to read token file: %w
What it means
The cached file token loader in internal/auth/tokenloader.go:42 wraps os.ReadFile errors with this message when it cannot read the bearer-token file at the given path. The loader caches the token for a configurable interval and re-reads the file when the interval expires, so this error can occur on the first read and on later reloads. On the initial load it is further wrapped as "failed to get token from file" by TokenProviderWithTime; on later reloads it is only logged as a warning and the last cached token is used.
Source
Thrown at internal/auth/tokenloader.go:42
lastRead time.Time
)
return func() (string, error) {
mu.Lock()
defer mu.Unlock()
now := timeFn()
// Special case: interval = 0 means "never reload after first load"
// Otherwise reload only if `interval` time has passed since last load.
if !lastRead.IsZero() && (interval == 0 || now.Sub(lastRead) < interval) {
return cachedToken, nil
}
// Read from file
b, err := os.ReadFile(filepath.Clean(path))
if err != nil {
return "", fmt.Errorf("failed to read token file: %w", err)
}
cachedToken = strings.TrimRight(string(b), "\r\n")
lastRead = now
return cachedToken, nil
}
}
// TokenProvider creates a token provider that handles file loading and error handling consistently.
func TokenProvider(path string, interval time.Duration, logger *zap.Logger) (func() string, error) {
return TokenProviderWithTime(path, interval, logger, time.Now) // Use real time.Now in production
}
// TokenProviderWithTime creates a token provider with injectable time (for testing)
func TokenProviderWithTime(path string, interval time.Duration, logger *zap.Logger, timeFn func() time.Time) (func() string, error) {
loader := cachedFileTokenLoader(path, interval, timeFn)
// current token loadView on GitHub (pinned to 806f444784)
Solutions
- Verify the configured path exists and is readable by the process (ls -l <path> as the same user); fix the path or the secret mount
- If the file is rotated, rotate atomically (write new file, rename into place) instead of removing then creating it
- Set interval=0 to disable reloading so the loader never re-reads after the first successful load
- Recreate the token file and restart the process if the initial load failed, since TokenProvider construction aborts on it
Example fix
// before // token file path: /var/run/secrets/token (file absent) // after // $ ls -l /var/run/secrets/token // -r-------- 1 app app 215 ... /var/run/secrets/token // or set interval to 0 to never reload after the first successful read
Defensive patterns
Strategy: fallback
Validate before calling
// check readability before relying on the provider
if info, err := os.Stat(tokenPath); err != nil {
return fmt.Errorf("token file %s not accessible: %w", tokenPath, err)
} else if info.IsDir() {
return fmt.Errorf("token path %s is a directory", tokenPath)
} Try / catch
tokenFn, err := auth.TokenProvider(tokenPath, interval, logger)
if err != nil {
// on reload failures the provider itself falls back to the last cached token,
// so only construction errors need handling here
logger.Error("token auth unavailable", zap.Error(err))
return err
} Prevention
- Mount secrets with atomic rotation (symlink swap, e.g. Kubernetes projected volumes) so the file is never absent
- Set interval=0 to disable reloads when the token never rotates
- Verify secret mount paths in deployment manifests match the configured token path
- Check file permissions are readable by the service user (0400/0444 owned by the app)
When it happens
Trigger: os.ReadFile(filepath.Clean(path)) failing because the file does not exist (ENOENT), the process lacks read permission (EACCES), the path is a directory, or — on a reload after the cache interval elapsed — the file was deleted or rotated away between reads.
Common situations: Kubernetes secret mounted at a different path than configured, or the volume not yet populated at startup; credential rotation that briefly removes the file; running locally without the token file the deployment config expects; wrong relative vs absolute path.
Related errors
- failed to get token from file: %w
- cannot load config file %s: %w
- cannot load index.html: %w
- cannot open index.html: %w
- failed to load password from file: %w
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/eede16605b94e6a1.
Report an issue: GitHub.