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

  1. Unwrap the error (errors.Unwrap / %w chain) to identify the root cause (EOF, timeout, no audio, no video).
  2. Retry Dial with backoff if the cause is transient (camera reboot, network blip).
  3. Validate the stream URL and credentials; confirm the camera is reachable (ping/ffprobe).
  4. 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

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)