AlexxIT/go2rtc · error
: can't send command
Error message
%s: can't send command %d
What it means
WriteCommand retries sending a command frame a bounded number of times; when all attempts are exhausted without success it returns "cs2: can't send command %d" identifying the command code. It means the command could not be delivered/acknowledged within the retry budget, usually because the connection is dead or the peer is unresponsive.
Solutions
- Check the connection state (c.err) before calling WriteCommand; reconnect first if the worker has failed
- Increase the retry count / retry timeout passed to WriteCommand for slow links
- Verify the peer is online and responsive (ping via msgPing) before issuing the command
- Implement command idempotency so a safe retry after reconnect does not double-execute the command
Example fix
// before
if err := conn.WriteCommand(cmd, payload); err != nil {
return fmt.Errorf("send failed: %w", err)
}
// after
if conn.Err() != nil {
if err := conn.Reconnect(); err != nil {
return fmt.Errorf("reconnect failed: %w", err)
}
}
if err := conn.WriteCommand(cmd, payload); err != nil {
return fmt.Errorf("send failed: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// verify connectivity before sending a command
func canSend(c *Conn) bool { return c != nil && c.Err() == nil } Type guard
func sendable(c *Conn) bool { return c != nil && c.Err() == nil } Try / catch
var err error
for i := 0; i < 3; i++ {
if canSend(conn) { break }
if err = conn.Reconnect(); err != nil { time.Sleep(backoff(i)); continue }
}
if err == nil { err = conn.WriteCommand(cmd, payload) } Prevention
- Check connection health before each command
- Size retry count/timeout to the worst-case link latency
- Ping the peer before critical commands
- Make commands idempotent so retries are safe
When it happens
Trigger: Calling WriteCommand (public) while the worker has exited due to a read error (c.err set), or the peer never consumes/acks the command before the repeat counter and timeout expire.
Common situations: Calling WriteCommand after the connection dropped; peer device offline or hung; retry count configured too low for a slow or lossy link.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- nest: max retries exceeded
- request failed after
- exec: timeout
- dvrip: can't probe medias
- camera not ready
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/1857a90aaaedeace.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/xiaomi/miss/cs2/conn.go:238
timeout := time.NewTicker(time.Second)
defer timeout.Stop()
c.cmdAck = func() {
repeat.Store(0)
timeout.Reset(1)
}
for {
if _, err := c.Conn.Write(req); err != nil {
return err
}
<-timeout.C
r := repeat.Add(-1)
if r < 0 {
return nil
}
if r == 0 {
return fmt.Errorf("%s: can't send command %d", "cs2", cmd)
}
}
}
const hdrSize = 32
func (c *Conn) ReadPacket() (hdr, payload []byte, err error) {
data, ok := c.channels[2].Pop()
if !ok {
return nil, nil, c.Error()
}
return data[:hdrSize], data[hdrSize:], nil
}
func (c *Conn) WritePacket(hdr, payload []byte) error {
const offset = 12
n := hdrSize + uint32(len(payload))View on GitHub (pinned to c245815e75)