gofr-dev/gofr · error

no token available

Error message

no token available

What it means

errTokenUnavailable is returned by FileTokenAuthConfig.currentToken (file_token_auth.go:25) when the in-memory cached token is an empty string at the moment a request needs a bearer header injected. Under normal construction this cannot happen (the constructor reads eagerly), so it guards the race where a refresh has wiped the token or the config was built without one.

Source

Thrown at pkg/gofr/service/file_token_auth.go:25

	"net/http"
	"os"
	"strings"
	"sync"
	"time"

	"gofr.dev/pkg/gofr/logging"
)

const (
	// DefaultTokenFilePath is the standard Kubernetes projected service account token mount path.
	DefaultTokenFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/token" // #nosec G101 -- file path, not a credential

	defaultRefreshInterval = 30 * time.Second
)

var (
	errEmptyTokenFile    = errors.New("token file is empty")
	errTokenUnavailable  = errors.New("no token available")
	errAuthHeaderPresent = errors.New("authorization header already set on request")
)

// FileTokenAuthConfig reads a bearer token from a local file and periodically
// re-reads it to support token rotation (e.g. Kubernetes projected service
// account tokens).
//
// The returned value implements Options, Observable and
// io.Closer. Call Close to stop the background refresh goroutine; it is safe
// to call Close multiple times.
type FileTokenAuthConfig struct {
	tokenFilePath   string
	refreshInterval time.Duration

	logger logging.Logger

	mu    sync.RWMutex
	token string

View on GitHub (pinned to 187eb24962)

Solutions

  1. Always create the auth config via NewFileTokenAuthConfig so the token is loaded before use.
  2. Check the file at tokenFilePath exists and is readable; refresh failures are logged at WARN by the refresh loop — fix the file so refresh repopulates the token.
  3. Retry the request after the next refresh interval once the token file is restored.
  4. Close the config and re-create it if the token source is permanently gone.

Example fix

// before
dec := &service.fileTokenDecorator{source: cfg} // cfg built by hand, token empty
// after
cfg, err := service.NewFileTokenAuthConfig(service.WithTokenFilePath(path)) // eager token load
Defensive patterns

Strategy: type-guard

Validate before calling

cfg, err := service.NewFileTokenAuthConfig(opts...)
if err != nil { return err } // ensures token loaded
if cfg == nil { return errors.New("nil auth config") }

Type guard

func tokenReady(cfg *service.FileTokenAuthConfig) bool {
	return cfg != nil // construction guarantees a non-empty cached token
}

Try / catch

headers, err := decorator.inject(headers)
if errors.Is(err, service.ErrTokenUnavailable) {
	// retry after refresh interval or recreate config
}

Prevention

When it happens

Trigger: A fileTokenDecorator method (Get/Post/Put/Patch/Delete with headers) calls inject -> currentToken while the cached f.token is "" — e.g. after a refresh failure path that cleared the token, or misuse of a zero-value FileTokenAuthConfig not created via NewFileTokenAuthConfig.

Common situations: Constructing the decorator manually and skipping NewFileTokenAuthConfig; the token file being deleted and refresh failing repeatedly leaving an unusable state; shutting the service down while requests are still in flight.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/7b6059854614e491. Report an issue: GitHub.