{"record":{"id":"9752478c8e16fee1","repo":"cloudflare/cloudflared","slug":"flow-is-in-use-by-another-connection","errorCode":null,"errorMessage":"flow is in use by another connection","messagePattern":"flow is in use by another connection","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quic/v3/manager.go","lineNumber":19,"sourceCode":"package v3\n\nimport (\n\t\"errors\"\n\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)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/quic/v3/manager.go#L1-L37","documentation":"ErrSessionBoundToOtherConn is returned when a registration already exists for the same RequestID but is bound to a different QUIC connection. QUICv3 datagram sessions are per-connection: migrating a flow to a new connection requires explicit migration handling, and silent re-binding would split the flow. The manager returns this error instead of overwriting the existing binding.","triggerScenarios":"Calling manager.RegisterSession(&request, eyeball) where s.sessions[request.RequestID] exists with session.ConnectionID() != conn.ID(). Also produced when handleSessionRegistrationDatagram receives a re-registration from a new connection without migration.","commonSituations":"Client reconnects after a network change and tries to register the same RequestID over a new QUIC connection; load-balancer shifting the client to a different edge connection; client bug reusing an old RequestID.","solutions":["Generate a fresh unique RequestID for each new connection instead of reusing the previous one","Use the library's session migration flow (handleSessionRegistrationDatagram / migration path) rather than plain re-registration","Tear down the old session (UnregisterSession) before registering on the new connection","Handle errors.Is(err, v3.ErrSessionBoundToOtherConn) on the client by restarting the flow with a new ID"],"exampleFix":"// before\n// client reconnect reused old requestID\n_, err := manager.RegisterSession(&request, newEyeball) // -> ErrSessionBoundToOtherConn\n// after\nrequest.RequestID = newRequestID() // unique per connection\n_, err := manager.RegisterSession(&request, newEyeball)","handlingStrategy":"try-catch","validationCode":"// client side: guarantee uniqueness before registering\nrequestID, err := cfdRequestID.New() // fresh ID per connection","typeGuard":null,"tryCatchPattern":"if _, err := manager.RegisterSession(&request, eyeball); errors.Is(err, v3.ErrSessionBoundToOtherConn) {\n    // flow lives on another connection: start a new flow with a new RequestID\n    return\n}","preventionTips":["Never reuse RequestIDs across connections","Use the official session migration API instead of re-registration","Unregister or expire old sessions before rebinding","Handle client reconnects with fresh flow IDs"],"tags":["quic","session","conflict","connection"],"backgroundTag":"conflicting-resource-states","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"}