{"record":{"id":"92b951584162cf0c","repo":"AlexxIT/go2rtc","slug":"xiaomi-probe-w","errorCode":null,"errorMessage":"xiaomi: probe: %w","messagePattern":"xiaomi: probe: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/xiaomi/miss/producer.go","lineNumber":68,"sourceCode":"\t\t},\n\t\tclient: client,\n\t}, nil\n}\n\nfunc probe(client *Client, audio bool) ([]*core.Media, error) {\n\t_ = client.SetDeadline(time.Now().Add(15 * time.Second))\n\n\tvar vcodec, acodec *core.Codec\n\n\tfor {\n\t\tpkt, err := client.ReadPacket()\n\t\tif err != nil {\n\t\t\tif vcodec != nil {\n\t\t\t\terr = fmt.Errorf(\"no audio\")\n\t\t\t} else if acodec != nil {\n\t\t\t\terr = fmt.Errorf(\"no video\")\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"xiaomi: probe: %w\", err)\n\t\t}\n\n\t\tswitch pkt.CodecID {\n\t\tcase codecH264:\n\t\t\tif vcodec == nil {\n\t\t\t\tbuf := annexb.EncodeToAVCC(pkt.Payload)\n\t\t\t\tif h264.NALUType(buf) == h264.NALUTypeSPS {\n\t\t\t\t\tvcodec = h264.AVCCToCodec(buf)\n\t\t\t\t}\n\t\t\t}\n\t\tcase codecH265:\n\t\t\tif vcodec == nil {\n\t\t\t\tbuf := annexb.EncodeToAVCC(pkt.Payload)\n\t\t\t\tif h265.NALUType(buf) == h265.NALUTypeVPS {\n\t\t\t\t\tvcodec = h265.AVCCToCodec(buf)\n\t\t\t\t}\n\t\t\t}\n\t\tcase codecPCMA:","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/xiaomi/miss/producer.go#L50-L86","documentation":"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.","triggerScenarios":"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>\".","commonSituations":"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.","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."],"exampleFix":"// before\nproducer, err := miss.Dial(ctx, url)\nif err != nil {\n    return err // opaque: xiaomi: probe: ...\n}\n// after\nproducer, err := miss.Dial(ctx, url)\nif err != nil {\n    var ctxErr error\n    if errors.Is(err, io.EOF) || errors.Is(err, context.DeadlineExceeded) {\n        ctxErr = retryWithBackoff(ctx, func() error { _, e := miss.Dial(ctx, url); return e })\n    }\n    return fmt.Errorf(\"dial xiaomi %s: %w\", url, err)\n}","handlingStrategy":"retry","validationCode":"// reachability check before Dial\nconn, err := net.DialTimeout(\"tcp\", host, 3*time.Second)\nif err != nil {\n    return fmt.Errorf(\"camera unreachable: %w\", err)\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"var lastErr error\nfor attempt := 0; attempt < 3; attempt++ {\n    producer, err := miss.Dial(ctx, url)\n    if err == nil {\n        return producer, nil\n    }\n    lastErr = err\n    if !errors.Is(err, io.EOF) && !errors.Is(err, context.DeadlineExceeded) {\n        break // non-transient\n    }\n    time.Sleep(time.Duration(attempt+1) * time.Second)\n}\nreturn nil, fmt.Errorf(\"xiaomi dial failed: %w\", lastErr)","preventionTips":["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."],"tags":["streaming","probe","camera","error-wrapping"],"backgroundTag":"stream-probe-failed","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}