{"record":{"id":"b868f66175d1cc3a","repo":"cloudflare/cloudflared","slug":"flow-registration-rate-limited","errorCode":null,"errorMessage":"flow registration rate limited","messagePattern":"flow registration rate limited","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quic/v3/manager.go","lineNumber":23,"sourceCode":"\t\"sync\"\n\n\t\"github.com/rs/zerolog\"\n\n\t\"github.com/cloudflare/cloudflared/ingress\"\n\t\"github.com/cloudflare/cloudflared/management\"\n\n\tcfdflow \"github.com/cloudflare/cloudflared/flow\"\n)\n\nvar (\n\t// ErrSessionNotFound indicates that a session has not been registered yet for the request id.\n\tErrSessionNotFound = errors.New(\"flow not found\")\n\t// ErrSessionBoundToOtherConn is returned when a registration already exists for a different connection.\n\tErrSessionBoundToOtherConn = errors.New(\"flow is in use by another connection\")\n\t// ErrSessionAlreadyRegistered is returned when a registration already exists for this connection.\n\tErrSessionAlreadyRegistered = errors.New(\"flow is already registered for this connection\")\n\t// ErrSessionRegistrationRateLimited is returned when a registration fails due to rate limiting on the number of active flows.\n\tErrSessionRegistrationRateLimited = errors.New(\"flow registration rate limited\")\n)\n\ntype SessionManager interface {\n\t// RegisterSession will register a new session if it does not already exist for the request ID.\n\t// During new session creation, the session will also bind the UDP socket for the origin.\n\t// If the session exists for a different connection, it will return [ErrSessionBoundToOtherConn].\n\tRegisterSession(request *UDPSessionRegistrationDatagram, conn DatagramConn) (Session, error)\n\t// GetSession returns an active session if available for the provided connection.\n\t// If the session does not exist, it will return [ErrSessionNotFound]. If the session exists for a different\n\t// connection, it will return [ErrSessionBoundToOtherConn].\n\tGetSession(requestID RequestID) (Session, error)\n\t// UnregisterSession will remove a session from the current session manager. It will attempt to close the session\n\t// before removal.\n\tUnregisterSession(requestID RequestID)\n}\n\ntype sessionManager struct {\n\tsessions     map[RequestID]Session","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/quic/v3/manager.go#L5-L41","documentation":"ErrSessionRegistrationRateLimited is returned when a session registration is rejected because the flow limiter has no capacity left: manager.RegisterSession calls s.limiter.Acquire(management.UDP) and maps any limiter rejection to this sentinel. It protects the server from resource exhaustion by capping the number of concurrent UDP flows.","triggerScenarios":"Calling RegisterSession (directly or via handleSessionRegistrationDatagram) when the UDP flow limiter is already at its configured maximum of active flows.","commonSituations":"Traffic spikes or flow leaks where sessions are registered but never unregistered, hitting the cap; overly low flow-limit configuration for the workload; a client opening thousands of UDP flows (or an abuse/flood pattern).","solutions":["Raise the UDP flow limit configuration if the workload legitimately needs more concurrent flows","Ensure sessions are unregistered on close/timeout so capacity is returned to the limiter","Add client-side backoff and retry on errors.Is(err, v3.ErrSessionRegistrationRateLimited)","Audit for leaked sessions (register-without-unregister) that slowly exhaust the limiter"],"exampleFix":"// before\n_, err := manager.RegisterSession(&request, eyeball) // rejects under load\n// after\n_, err := manager.RegisterSession(&request, eyeball)\nif errors.Is(err, v3.ErrSessionRegistrationRateLimited) {\n    time.Sleep(backoff) // exponential backoff before retry\n    return retry(ctx)\n}","handlingStrategy":"retry","validationCode":"// check flow usage before registration if the limiter exposes a count\n// e.g. if limiter.Active(management.UDP) >= maxFlows { wait }","typeGuard":null,"tryCatchPattern":"_, err := manager.RegisterSession(&request, eyeball)\nif errors.Is(err, v3.ErrSessionRegistrationRateLimited) {\n    select {\n    case <-time.After(backoff):\n        return retryRegister(ctx)\n    case <-ctx.Done():\n        return ctx.Err()\n    }\n}","preventionTips":["Unregister sessions promptly on close to return capacity","Set the UDP flow limit above steady-state concurrent flows","Apply exponential backoff on the client side","Monitor for leaked sessions that gradually exhaust the limiter"],"tags":["quic","session","rate-limit","capacity"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}