gofiber/fiber · error

fiber: keyauth error_description requires error

Error message

fiber: keyauth error_description requires error

What it means

RFC 6750 requires error_description to appear only alongside an error parameter in a WWW-Authenticate challenge. keyauth enforces this: setting Config.ErrorDescription while Config.Error is empty panics. The descriptionqualifies the error; without an error code it has no meaning to the client.

Solutions

  1. Also set Config.Error to one of the three allowed codes (e.g. keyauth.ErrorInvalidToken).
  2. Remove ErrorDescription if you do not need a human-readable hint.
  3. Validate at config load: if ErrorDescription != "" then Error must be non-empty.

Example fix

// before
app.Use(keyauth.New(keyauth.Config{
    Validator:        v,
    ErrorDescription: "the token has expired",
}))

// after
app.Use(keyauth.New(keyauth.Config{
    Validator:        v,
    Error:            keyauth.ErrorInvalidToken,
    ErrorDescription: "the token has expired",
}))
Defensive patterns

Strategy: validation

Validate before calling

if cfg.ErrorDescription != "" && cfg.Error == "" {
    log.Fatal("keyauth: ErrorDescription requires Error")
}

Prevention

When it happens

Trigger: keyauth.Config{ErrorDescription: "token expired"} with no Error set. Also reached when Error is populated conditionally but ErrorDescription is set unconditionally.

Common situations: Wanting a human-readable challenge message but forgetting the mandatory machine-readable error code; refactoring that removes the Error assignment but leaves ErrorDescription; building the challenge fields from separate config keys that got out of sync.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/b52ad8f0eaa85308. Report an issue: GitHub.

Appendix: source

Thrown at middleware/keyauth/config.go:140

		cfg.SuccessHandler = ConfigDefault.SuccessHandler
	}
	if cfg.ErrorHandler == nil {
		cfg.ErrorHandler = ConfigDefault.ErrorHandler
	}

	if len(getAuthSchemes(cfg.Extractor)) == 0 && cfg.Challenge == "" {
		cfg.Challenge = fmt.Sprintf("ApiKey realm=%q", cfg.Realm)
	}

	if cfg.Error != "" {
		switch cfg.Error {
		case ErrorInvalidRequest, ErrorInvalidToken, ErrorInsufficientScope:
		default:
			panic("fiber: keyauth unsupported error token")
		}
	}
	if cfg.ErrorDescription != "" && cfg.Error == "" {
		panic("fiber: keyauth error_description requires error")
	}
	if cfg.ErrorURI != "" {
		if cfg.Error == "" {
			panic("fiber: keyauth error_uri requires error")
		}
		if u, err := url.Parse(cfg.ErrorURI); err != nil || !u.IsAbs() {
			panic("fiber: keyauth error_uri must be absolute")
		}
	}
	if cfg.Error == ErrorInsufficientScope {
		if cfg.Scope == "" {
			panic("fiber: keyauth insufficient_scope requires scope")
		}
		for scope := range strings.SplitSeq(cfg.Scope, " ") {
			if scope == "" || !isScopeToken(scope) {
				panic("fiber: keyauth scope contains invalid token")
			}
		}

View on GitHub (pinned to a105acad6c)