m1k1o/neko · error · ErrWebRTCDataChannelNotFound
webrtc data channel not found
Error message
webrtc data channel not found
What it means
ErrWebRTCDataChannelNotFound is a sentinel error in the neko types package indicating that a WebRTC peer lookup for its data channel failed — the expected data channel (e.g. for cursor/control messages) has not been created or has not been opened yet. Code returns it when it tries to use a peer's data channel that is nil or absent.
Source
Thrown at server/pkg/types/webrtc.go:10
package types
import (
"errors"
"github.com/pion/webrtc/v4"
)
var (
ErrWebRTCDataChannelNotFound = errors.New("webrtc data channel not found")
ErrWebRTCConnectionNotFound = errors.New("webrtc connection not found")
ErrWebRTCStreamNotFound = errors.New("webrtc stream not found")
)
type ICEServer struct {
URLs []string `mapstructure:"urls" json:"urls"`
Username string `mapstructure:"username" json:"username,omitempty"`
Credential string `mapstructure:"credential" json:"credential,omitempty"`
}
type PeerVideo struct {
Disabled bool `json:"disabled"`
ID string `json:"id"`
Video string `json:"video"` // TODO: Remove this, used for compatibility with old clients.
Auto bool `json:"auto"`
}
type PeerVideoRequest struct {View on GitHub (pinned to b0f01cedea)
Solutions
- Ensure the WebRTC handshake (offer/answer, ICE) completed and the data channel is 'open' before sending messages.
- Check the client logs/browser console for ICE connection failures and fix STUN/TURN (ICEServers) configuration.
- Retry the send after the peer signals its data channel opened.
- Destroy and recreate the peer if the channel is permanently closed.
- Verify client and server neko versions are compatible (pion webrtc v4 negotiation).
Example fix
// before
err := peer.SendCursorPosition(x, y) // ErrWebRTCDataChannelNotFound if channel not open
// after
if peer.DataChannel() == nil || peer.DataChannel().ReadyState() != webrtc.DataChannelStateOpen {
return nil // or queue the message until the channel opens
}
err := peer.SendCursorPosition(x, y) Defensive patterns
Strategy: try-catch
Validate before calling
// only send after the data channel is open
if ch := peer.DataChannel(); ch == nil || ch.ReadyState() != webrtc.DataChannelStateOpen {
return errors.New("data channel not open yet")
} Type guard
func DataChannelReady(p types.WebRTCPeer) bool {
ch := p.DataChannel()
return ch != nil && ch.ReadyState() == webrtc.DataChannelStateOpen
} Try / catch
if err := peer.SendCursorPosition(x, y); err != nil {
if errors.Is(err, types.ErrWebRTCDataChannelNotFound) {
// queue and resend once the channel opens
return
}
return err
} Prevention
- Wait for onopen/onstatechange before sending messages.
- Validate ICE/TURN configuration so connections complete.
- Handle peer destroy events by dropping pending sends.
- Keep client and server WebRTC library versions aligned.
When it happens
Trigger: Sending cursor position/cursor image over a peer whose data channel was never negotiated or not yet open; using a WebRTCPeer before the signaling/ICE handshake completes; after the data channel was closed by either side.
Common situations: Clients calling control APIs before the WebRTC connection finishes opening; ICE connection failures leaving the channel unestablished; browsers blocking WebRTC data channels (extensions, strict networks); peers destroyed mid-use.
Related errors
- webrtc connection not found
- webrtc stream not found
- member does not exist
- session not found
- plugin '%s' not found
AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01).
Data as JSON: /api/errors/9404ff53358a2c22.
Report an issue: GitHub.