{"record":{"id":"77225ffa67f068b9","repo":"livekit/livekit","slug":"track-not-bound","errorCode":null,"errorMessage":"track not bound","messagePattern":"track not bound","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/rtc/errors.go","lineNumber":40,"sourceCode":"\tErrRoomClosed               = errors.New(\"room has already closed\")\n\tErrParticipantSessionClosed = errors.New(\"participant session is already closed\")\n\tErrPermissionDenied         = errors.New(\"no permissions to access the room\")\n\tErrMaxParticipantsExceeded  = errors.New(\"room has exceeded its max participants\")\n\tErrLimitExceeded            = errors.New(\"node has exceeded its configured limit\")\n\tErrAlreadyJoined            = errors.New(\"a participant with the same identity is already in the room\")\n\tErrDataChannelUnavailable   = errors.New(\"data channel is not available\")\n\tErrDataChannelBufferFull    = errors.New(\"data channel buffer is full\")\n\tErrTransportFailure         = errors.New(\"transport failure\")\n\tErrEmptyIdentity            = errors.New(\"participant identity cannot be empty\")\n\tErrEmptyParticipantID       = errors.New(\"participant ID cannot be empty\")\n\tErrMissingGrants            = errors.New(\"VideoGrant is missing\")\n\tErrInternalError            = errors.New(\"internal error\")\n\n\t// Track subscription related\n\tErrNoTrackPermission         = errors.New(\"participant is not allowed to subscribe to this track\")\n\tErrNoSubscribePermission     = errors.New(\"participant is not given permission to subscribe to tracks\")\n\tErrTrackNotFound             = errors.New(\"track cannot be found\")\n\tErrTrackNotBound             = errors.New(\"track not bound\")\n\tErrSubscriptionLimitExceeded = errors.New(\"participant has exceeded its subscription limit\")\n\n\tErrNoSubscribeMetricsPermission = errors.New(\"participant is not given permission to subscribe to metrics\")\n)\n","sourceCodeStart":22,"sourceCodeEnd":45,"githubUrl":"https://github.com/livekit/livekit/blob/ee45c3f0b1a83bf4352dbccb6607ebf70b2a5de6/pkg/rtc/errors.go#L22-L45","documentation":"ErrTrackNotBound indicates that a MediaTrackSubscription never completed binding the subscribed track to the subscriber's receiver within the subscription timeout. In pkg/rtc/subscriptionmanager.go:584-585, after wait exceeds subscriptionTimeout, the manager logs \"track not bound after timeout\", records it with telemetry, and reports it via OnSubscriptionError. It signals the negotiation/subscription handshake did not finish in time.","triggerScenarios":"Returned by reconcileSubscription; raised as a timeout in the subscription manager when the track's bind step (SDP/negotiation completing for the subscriber) does not happen before subscriptionTimeout elapses.","commonSituations":"Slow or stalled peer connection negotiation under poor network conditions; subscriber pause/negotiation storms with many tracks; a subscriber connection that went stale after resume.","solutions":["Verify the subscriber's peer connection completed negotiation; restart the connection if ICE/negotiation is stalled.","Check server logs around the timeout for negotiation failures or pauses.","Retry the subscription (re-subscribe to the track) once the connection is healthy."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, rtc.ErrTrackNotBound) {\n    logger.Warnw(\"subscription bind timed out\", err)\n    resubscribe(trackSID) // after confirming connection health\n}","preventionTips":["Monitor subscription latency and negotiation health in telemetry.","Keep subscriptionTimeout well above worst-case negotiation time.","Restart stalled subscriber peer connections before re-subscribing."],"tags":["rtc","subscription","timeout","negotiation"],"backgroundTag":"subscription-bind-timeout","analyzedSha":"ee45c3f0b1a83bf4352dbccb6607ebf70b2a5de6","analyzedAt":"2026-09-02T03:56:08.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}