gofr-dev/gofr · error
authorization header already set on request
Error message
authorization header already set on request
What it means
errAuthHeaderPresent is returned by fileTokenDecorator.inject (file_token_auth.go:26) when the outgoing request already carries a non-empty Authorization header. FileTokenAuthConfig is an automatic bearer-token injector; it refuses to silently overwrite a caller-supplied credential, wrapping the sentinel in AuthErr so the caller knows their explicit header collided with injection.
Source
Thrown at pkg/gofr/service/file_token_auth.go:26
"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
- Remove the Authorization header from your explicit headers map and let FileTokenAuthConfig inject the file-based token.
- If you need a custom credential, do not add FileTokenAuthConfig (AddOption) to that HTTP service.
- If you intended both, chain two services instead of mixing header auth with file-token auth on one request.
- Check for empty-string-only headers: the guard only fires when the existing value is non-empty, so clearing the header fixes it.
Example fix
// before
svc.GetWithHeaders(ctx, "/x", nil, map[string]string{"Authorization": "Bearer manual"})
// after
svc.GetWithHeaders(ctx, "/x", nil, nil) // token injected from file Defensive patterns
Strategy: validation
Validate before calling
if h, ok := headers["Authorization"]; ok && h != "" {
delete(headers, "Authorization") // let file-token auth inject
} Type guard
func hasAuthHeader(headers map[string]string) bool {
v, ok := headers["Authorization"]
return ok && v != ""
} Try / catch
resp, err := svc.GetWithHeaders(ctx, path, qp, headers)
var ae service.AuthErr
if errors.As(err, &ae) && errors.Is(ae.Err, errAuthHeaderPresent) {
// drop the manual Authorization header and retry once
} Prevention
- Pick one auth mechanism per service: file-token injection OR manual headers, never both.
- Audit middleware/interceptors for code that sets Authorization on outgoing requests.
- When migrating to decorated services, remove legacy header-setting code.
- Document in team conventions that explicit Authorization headers are rejected on decorated services.
When it happens
Trigger: Calling any GetWithHeaders/PostWithHeaders/PutWithHeaders/PatchWithHeaders/DeleteWithHeaders on a service decorated with FileTokenAuthConfig while passing headers containing Authorization with a non-empty value (also exercised directly by TestFileTokenAuthConfig_RejectsExistingAuthHeader).
Common situations: Adding your own "Authorization: Bearer <my-token>" in headers while also enabling file-token auth on the service; middleware that sets auth headers upstream of the decorator; migrating code that previously did manual auth into a decorated service.
Related errors
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/91ddd18be6e32ac2.
Report an issue: GitHub.