{"id":"aefc9be827b6ae83","repo":"gofiber/fiber","slug":"fiber-keyauth-error-uri-requires-error","errorCode":null,"errorMessage":"fiber: keyauth error_uri requires error","messagePattern":"fiber: keyauth error_uri requires error","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/keyauth/config.go","lineNumber":144,"sourceCode":"\t}\n\n\tif len(getAuthSchemes(cfg.Extractor)) == 0 && cfg.Challenge == \"\" {\n\t\tcfg.Challenge = fmt.Sprintf(\"ApiKey realm=%q\", cfg.Realm)\n\t}\n\n\tif cfg.Error != \"\" {\n\t\tswitch cfg.Error {\n\t\tcase ErrorInvalidRequest, ErrorInvalidToken, ErrorInsufficientScope:\n\t\tdefault:\n\t\t\tpanic(\"fiber: keyauth unsupported error token\")\n\t\t}\n\t}\n\tif cfg.ErrorDescription != \"\" && cfg.Error == \"\" {\n\t\tpanic(\"fiber: keyauth error_description requires error\")\n\t}\n\tif cfg.ErrorURI != \"\" {\n\t\tif cfg.Error == \"\" {\n\t\t\tpanic(\"fiber: keyauth error_uri requires error\")\n\t\t}\n\t\tif u, err := url.Parse(cfg.ErrorURI); err != nil || !u.IsAbs() {\n\t\t\tpanic(\"fiber: keyauth error_uri must be absolute\")\n\t\t}\n\t}\n\tif cfg.Error == ErrorInsufficientScope {\n\t\tif cfg.Scope == \"\" {\n\t\t\tpanic(\"fiber: keyauth insufficient_scope requires scope\")\n\t\t}\n\t\tfor scope := range strings.SplitSeq(cfg.Scope, \" \") {\n\t\t\tif scope == \"\" || !isScopeToken(scope) {\n\t\t\t\tpanic(\"fiber: keyauth scope contains invalid token\")\n\t\t\t}\n\t\t}\n\t} else if cfg.Scope != \"\" {\n\t\tpanic(\"fiber: keyauth scope requires insufficient_scope error\")\n\t}\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/keyauth/config.go#L126-L162","documentation":"The keyauth Config.ErrorURI field (RFC 6750 error_uri) points clients to a page describing the error and is only valid alongside an Error code. Setting ErrorURI while Error is empty panics in configDefault() because the challenge would be malformed without its required error parameter.","triggerScenarios":"Calling keyauth.New() with a non-empty Config.ErrorURI but Config.Error left empty. The library checks ErrorURI before Error in the validation order, so even a valid absolute URL here panics if Error is unset.","commonSituations":"Adding a help link to 401 responses without specifying why the request failed. Reorganizing config and dropping the Error field while leaving the URI. Assuming ErrorURI works as a standalone documentation pointer.","solutions":["Always set Config.Error to a valid code (invalid_request, invalid_token, insufficient_scope) when ErrorURI is set.","If you only want to send a help link, move that logic into a custom Config.ErrorHandler instead.","Use a config-building helper that asserts Error is set before allowing ErrorURI."],"exampleFix":"// before\napp.Use(keyauth.New(keyauth.Config{\n    Validator: validateKey,\n    ErrorURI:  \"https://example.com/docs/auth-errors\",\n}))\n// after\napp.Use(keyauth.New(keyauth.Config{\n    Validator: validateKey,\n    Error:     keyauth.ErrorInvalidToken,\n    ErrorURI:  \"https://example.com/docs/auth-errors\",\n}))","handlingStrategy":"validation","validationCode":"if cfg.ErrorURI != \"\" && cfg.Error == \"\" {\n    log.Fatal(\"keyauth: ErrorURI requires Error to be set\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set the Error code first, then add ErrorURI/ErrorDescription.","Use a config helper that asserts Error is non-empty before allowing sub-fields."],"tags":["keyauth","config","auth","rfc6750","panic"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}