AlexxIT/go2rtc · error
: can't send command
Error message
%s: can't send command %d
What it means
WriteCommand retries sending a TUTK control command a fixed number of times against a timeout; each failed attempt decrements a repeat counter. When the counter reaches zero the send still has not succeeded and this error is returned, meaning the command (identified by ctrlType) could not be delivered to the device.
Solutions
- Verify the device is reachable and the TUTK session (from Dial) established before sending commands.
- Increase the repeat count/timeout used by WriteCommand to tolerate slow links.
- Check NAT/firewall/relay configuration for the TUTK channel and retry Dial if the session went stale.
- Log ctrlType and inspect the device side to confirm it is awake and accepting commands.
Example fix
// before
resp, err := conn.WriteCommand(ctrlType)
// after
if err := conn.Ping(); err != nil {
conn, err = tutk.Dial(uid)
if err != nil { log.Fatal(err) }
}
resp, err := conn.WriteCommand(ctrlType) Defensive patterns
Strategy: retry
Validate before calling
// Check session liveness before sending commands
if conn == nil || conn.Closed() || !conn.SessionEstablished() {
conn, err = tutk.Dial(uid)
if err != nil { return err }
} Try / catch
var resp []byte
err := retry.Do(3, time.Second, func() error {
var e error
resp, e = conn.WriteCommand(ctrlType)
return e
})
if err != nil {
conn, err = redial(uid) // re-establish before giving up
} Prevention
- Verify device reachability before sending control commands
- Increase retry/timeout budget for slow or flaky networks
- Re-dial stale sessions instead of reusing them after timeouts
- Monitor NAT/relay health for P2P connectivity issues
When it happens
Trigger: Calling WriteCommand (directly or via xiaofangLogin/login) when the underlying TUTK session cannot accept the frame within the retry budget — e.g. channel not established, device unreachable, or per-attempt timeout expiring repeatedly.
Common situations: Camera offline or on a flaky Wi-Fi link; P2P session not yet fully established when login commands are issued; firewall/NAT blocking the TUTK relay; too-short retry/timeout configuration for slow networks.
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
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/2c8dbdfb717c6c1f.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/tutk/conn.go:143
c.cmdAck = func() {
repeat.Store(0)
timeout.Reset(1)
}
buf := c.session.SendIOCtrl(ctrlType, ctrlData)
for {
if err := c.session.SessionWrite(0, buf); 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", "tutk", ctrlType)
}
}
}
func (c *Conn) ReadPacket() (hdr, payload []byte, err error) {
return c.session.RecvFrameData()
}
func (c *Conn) WritePacket(hdr, payload []byte) error {
buf := c.session.SendFrameData(hdr, payload)
return c.session.SessionWrite(1, buf)
}
func (c *Conn) Error() error {
if c.err != nil {
return c.err
}
return io.EOFView on GitHub (pinned to c245815e75)