{"record":{"id":"9d81b5583d179c89","repo":"crowdsecurity/crowdsec","slug":"bouncer-not-found","errorCode":null,"errorMessage":"bouncer not found","messagePattern":"bouncer not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"pkg/apiserver/controllers/v1/utils.go","lineNumber":19,"sourceCode":"package v1\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n\n\tjwt \"github.com/appleboy/gin-jwt/v2\"\n\t\"github.com/gin-gonic/gin\"\n\n\tmiddlewares \"github.com/crowdsecurity/crowdsec/pkg/apiserver/middlewares/v1\"\n\t\"github.com/crowdsecurity/crowdsec/pkg/database/ent\"\n)\n\nfunc getBouncerFromContext(ctx *gin.Context) (*ent.Bouncer, error) {\n\tbouncerInterface, exist := ctx.Get(middlewares.BouncerContextKey)\n\tif !exist {\n\t\treturn nil, errors.New(\"bouncer not found\")\n\t}\n\n\tbouncerInfo, ok := bouncerInterface.(*ent.Bouncer)\n\tif !ok {\n\t\treturn nil, errors.New(\"bouncer not found\")\n\t}\n\n\treturn bouncerInfo, nil\n}\n\nfunc isUnixSocket(c *gin.Context) bool {\n\tif localAddr, ok := c.Request.Context().Value(http.LocalAddrContextKey).(net.Addr); ok {\n\t\treturn strings.HasPrefix(localAddr.Network(), \"unix\")\n\t}\n\n\treturn false\n}\n","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/controllers/v1/utils.go#L1-L37","documentation":"getBouncerFromContext extracts the authenticated bouncer (*ent.Bouncer) that the JWT/auth middleware stored in the gin context under middlewares.BouncerContextKey. It returns \"bouncer not found\" when the key is absent entirely, meaning the request reached a bouncer-only endpoint without having gone through the bouncer authentication middleware. Callers such as GetDecision, StreamDecision and the usage metrics handlers abort with 401 when this happens.","triggerScenarios":"An HTTP request hits /v1/decisions, /v1/decision/stream, or the Prometheus/usage-metrics bouncer endpoints without the middleware having authenticated a bouncer — e.g. the route is mounted without the bouncer auth middleware, a test constructs the gin context directly without setting middlewares.BouncerContextKey, or the middleware failed but did not abort before the handler ran.","commonSituations":"Custom reverse-proxy setups that strip or bypass the API-key auth step; integration tests that call handlers with a bare gin test context; misconfigured LAPI where tls auth or api-key auth silently failed; calling internal handler functions directly from other code.","solutions":["Ensure the bouncer authentication middleware (apikey/TLS) is registered on the route before the handler so it sets middlewares.BouncerContextKey","Register the bouncer with `cscli bouncers add <name>` and send the returned API key as the X-Api-Key header","In tests, set ctx.Set(middlewares.BouncerContextKey, &ent.Bouncer{...}) before invoking the handler","Check API server logs for an earlier middleware failure that skipped context population"],"exampleFix":"// before: route without auth\ngroup.GET(\"/decisions\", ctrl.GetDecision)\n// after: route with bouncer auth middleware\ngroup.GET(\"/decisions\", mw.BouncerAuth, ctrl.GetDecision)","handlingStrategy":"try-catch","validationCode":"if _, ok := c.Get(middlewares.BouncerContextKey); !ok {\n    c.AbortWithStatusJSON(401, gin.H{\"message\": \"authenticate first\"})\n    return\n}","typeGuard":"v, exists := c.Get(middlewares.BouncerContextKey)\nbouncer, ok := v.(*ent.Bouncer)\nif !exists || !ok || bouncer == nil { /* unauthenticated */ }","tryCatchPattern":"bouncer, err := getBouncerFromContext(c)\nif err != nil {\n    c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{\"message\": \"bouncer not found\"})\n    return\n}","preventionTips":["Always register the apikey/TLS bouncer middleware before bouncer-facing handlers","When testing handlers, seed the gin context with middlewares.BouncerContextKey","Register bouncers with cscli bouncers add and send X-Api-Key on every request"],"tags":["authentication","lapi","bouncer","gin"],"backgroundTag":"entity-not-found","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}