{"id":"bf08cfdd964db909","repo":"gofiber/fiber","slug":"missing-or-invalid-api-key","errorCode":null,"errorMessage":"missing or invalid API Key","messagePattern":"missing or invalid API Key","errorType":"validation","errorClass":"ErrMissingOrMalformedAPIKey","httpStatus":null,"severity":"error","filePath":"middleware/keyauth/keyauth.go","lineNumber":26,"sourceCode":"\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/fiber/v3/extractors\"\n\t\"github.com/gofiber/fiber/v3/internal/redact\"\n\t\"github.com/gofiber/fiber/v3/middleware/logger\"\n\t\"github.com/gofiber/utils/v2\"\n)\n\n// The contextKey type is unexported to prevent collisions with context keys defined in\n// other packages.\ntype contextKey int\n\n// The keys for the values in context\nconst (\n\ttokenKey contextKey = iota\n)\n\n// ErrMissingOrMalformedAPIKey is returned when the API key is missing or invalid.\nvar ErrMissingOrMalformedAPIKey = errors.New(\"missing or invalid API Key\")\n\nvar registerLogContextTagsOnce sync.Once\n\n// New creates a new middleware handler\nfunc New(config ...Config) fiber.Handler {\n\tregisterLogContextTagsOnce.Do(registerLogContextTags)\n\n\t// Init config\n\tcfg := configDefault(config...)\n\n\t// Determine the auth schemes from the extractor chain.\n\tauthSchemes := getAuthSchemes(cfg.Extractor)\n\n\t// The challenge value only depends on config, so build it once instead of\n\t// re-formatting it on every 401/407 response.\n\tchallengeValue := cfg.Challenge\n\tif len(authSchemes) > 0 {\n\t\tchallenges := make([]string, 0, len(authSchemes))","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/keyauth/keyauth.go#L8-L44","documentation":"Returned by keyauth middleware (keyauth.go:26) when the configured Extractor cannot find an API key in the request, or when the Validator function rejects the extracted key. The error replaces the generic extractors.ErrNotFound with this keyauth-specific message (keyauth.go:76-79). It is passed to the ErrorHandler which by default returns 401 Unauthorized with a WWW-Authenticate challenge.","triggerScenarios":"A request to a protected route carries no API key in any of the configured extraction sources (default: Authorization header with Bearer scheme, then API-Key header, then query param 'key'); or the key is present but the Validator function returns false/an error. The extractor chain is tried in order and this fires only when all sources fail or validation fails.","commonSituations":"Client forgot to include the API key header; using the wrong header name (custom AuthHeader vs default); sending the key in the body instead of header/query; token expired or revoked (Validator rejects); mismatch between the scheme the client uses and what FromAuthHeader expects (e.g. 'Token' vs 'Bearer').","solutions":["Ensure the client sends the API key in the location and format the extractor expects (default: 'Authorization: Bearer <key>').","If using a custom header, set Config.AuthHeader / configure the Extractor chain to read from it.","Verify the Validator function logic — log the failure reason to distinguish missing vs invalid keys.","Customize the ErrorHandler to return a helpful message guiding clients on the expected key format."],"exampleFix":"// before — client sends key in wrong header\ncurl -H 'X-Token: abc123' https://app/api\n// after — use the scheme the extractor is configured for\ncurl -H 'Authorization: Bearer abc123' https://app/api\n\n// or configure keyauth to read the custom header\napp.Use(keyauth.New(keyauth.Config{\n  Validator: func(c fiber.Ctx, key string) (bool, error) { return key == validKey, nil },\n  AuthHeader: \"X-Token\",\n  AuthScheme: \"\",\n}))","handlingStrategy":"validation","validationCode":"// Client: verify the key and header before sending\nif apiKey == \"\" {\n    return errors.New(\"API key is required\")\n}\nreq.Header.Set(\"Authorization\", \"Bearer \"+apiKey)","typeGuard":null,"tryCatchPattern":"// Distinguish missing vs invalid in the error handler\ncfg.ErrorHandler = func(c fiber.Ctx, err error) error {\n    if errors.Is(err, keyauth.ErrMissingOrMalformedAPIKey) {\n        return c.Status(401).JSON(fiber.Map{\"error\":\"API key missing or invalid. Send it as 'Authorization: Bearer <key>'.\"})\n    }\n    return err\n}","preventionTips":["Standardize on one key location and document it for API consumers.","Ensure the Validator logs rejection reasons to distinguish missing vs revoked keys.","Match the AuthScheme to what clients actually send."],"tags":["keyauth","authentication","security","api","headers"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}