AlexxIT/go2rtc · error
xiaomi: probe
Error message
xiaomi: probe: %w
What it means
Generic wrapper for any failure raised inside the Xiaomi stream probe (pkg/xiaomi/miss producer). When client.ReadPacket fails during probe, whatever error results (transport failure, or the synthesized "no audio"/"no video" errors) is wrapped with the "xiaomi: probe: %w" prefix before being returned from Dial.
Solutions
- Unwrap the error (errors.Unwrap / %w chain) to identify the root cause (EOF, timeout, no audio, no video).
- Retry Dial with backoff if the cause is transient (camera reboot, network blip).
- Validate the stream URL and credentials; confirm the camera is reachable (ping/ffprobe).
- Inspect camera firmware/settings if the probe consistently fails before codec negotiation completes.
Example fix
// before
producer, err := miss.Dial(ctx, url)
if err != nil {
return err // opaque: xiaomi: probe: ...
}
// after
producer, err := miss.Dial(ctx, url)
if err != nil {
var ctxErr error
if errors.Is(err, io.EOF) || errors.Is(err, context.DeadlineExceeded) {
ctxErr = retryWithBackoff(ctx, func() error { _, e := miss.Dial(ctx, url); return e })
}
return fmt.Errorf("dial xiaomi %s: %w", url, err)
} Defensive patterns
Strategy: retry
Validate before calling
// reachability check before Dial
conn, err := net.DialTimeout("tcp", host, 3*time.Second)
if err != nil {
return fmt.Errorf("camera unreachable: %w", err)
}
conn.Close() Try / catch
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
producer, err := miss.Dial(ctx, url)
if err == nil {
return producer, nil
}
lastErr = err
if !errors.Is(err, io.EOF) && !errors.Is(err, context.DeadlineExceeded) {
break // non-transient
}
time.Sleep(time.Duration(attempt+1) * time.Second)
}
return nil, fmt.Errorf("xiaomi dial failed: %w", lastErr) Prevention
- Always use errors.Is/errors.As on the wrapped chain to find the root cause.
- Apply retry with backoff for transient transport failures only.
- Health-check the camera (TCP/RTSP) before dialing.
- Log the unwrapped cause to distinguish no-audio/no-video from network errors.
When it happens
Trigger: Any call to Dial where the underlying ReadPacket loop errors: socket closed, EOF, timeout, or the synthesized no-audio/no-video conditions; all surface as "xiaomi: probe: <cause>".
Common situations: Camera offline or rebooting; wrong stream URL/port; expired device session/token; network timeout mid-handshake; firmware dropping the connection before codec info is complete.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/92b951584162cf0c.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/xiaomi/miss/producer.go:68
},
client: client,
}, nil
}
func probe(client *Client, audio bool) ([]*core.Media, error) {
_ = client.SetDeadline(time.Now().Add(15 * time.Second))
var vcodec, acodec *core.Codec
for {
pkt, err := client.ReadPacket()
if err != nil {
if vcodec != nil {
err = fmt.Errorf("no audio")
} else if acodec != nil {
err = fmt.Errorf("no video")
}
return nil, fmt.Errorf("xiaomi: probe: %w", err)
}
switch pkt.CodecID {
case codecH264:
if vcodec == nil {
buf := annexb.EncodeToAVCC(pkt.Payload)
if h264.NALUType(buf) == h264.NALUTypeSPS {
vcodec = h264.AVCCToCodec(buf)
}
}
case codecH265:
if vcodec == nil {
buf := annexb.EncodeToAVCC(pkt.Payload)
if h265.NALUType(buf) == h265.NALUTypeVPS {
vcodec = h265.AVCCToCodec(buf)
}
}
case codecPCMA:View on GitHub (pinned to c245815e75)