{"record":{"id":"7874520918ff7023","repo":"fatedier/frp","slug":"wait-detect-message-canceled","errorCode":null,"errorMessage":"wait detect message canceled","messagePattern":"wait detect message canceled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/nathole/nathole.go","lineNumber":286,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\tlConn.Close()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase resultCh <- result{lConn: lConn, raddr: addr}:\n\t\t\tdefault:\n\t\t\t\tlConn.Close()\n\t\t\t}\n\t\t}(conn)\n\t}\n\n\tselect {\n\tcase result := <-resultCh:\n\t\treturn result.lConn, result.raddr, nil\n\tcase <-time.After(timeout):\n\t\treturn nil, nil, fmt.Errorf(\"wait detect message timeout\")\n\tcase <-ctx.Done():\n\t\treturn nil, nil, fmt.Errorf(\"wait detect message canceled\")\n\t}\n}\n\nfunc waitDetectMessage(\n\tctx context.Context, conn *net.UDPConn, sid string, key []byte,\n\ttimeout time.Duration, role string,\n) (*net.UDPAddr, error) {\n\txl := xlog.FromContextSafe(ctx)\n\tfor {\n\t\tbuf := pool.GetBuf(1024)\n\t\t_ = conn.SetReadDeadline(time.Now().Add(timeout))\n\t\tn, raddr, err := conn.ReadFromUDP(buf)\n\t\t_ = conn.SetReadDeadline(time.Time{})\n\t\tif err != nil {\n\t\t\tpool.PutBuf(buf)\n\t\t\treturn nil, err\n\t\t}\n\t\txl.Debugf(\"get udp message local %s, from %s\", conn.LocalAddr(), raddr)","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/nathole/nathole.go#L268-L304","documentation":"MakeHole aborted because the parent context was canceled while waiting for detect messages across the multiple listen sockets. This is a caller-initiated cancellation (shutdown, visit canceled, upper-layer deadline), not a network failure itself.","triggerScenarios":"The ctx passed into MakeHole is canceled while the select over resultCh/time.After is blocked — e.g. frpc shuts down, the visitor proxy is closed, or a parent timeout fires first.","commonSituations":"User cancels the visit or stops frpc during hole punching; a wrapping context deadline (shorter than the detect timeout) expires; graceful shutdown racing an in-flight P2P connection setup.","solutions":["No defect: treat as a clean cancel; ensure the caller distinguishes ctx.Err() from real punch failures","If premature, lengthen or remove the parent deadline so it exceeds DetectBehavior.ReadTimeoutMs","Avoid stopping frpc or closing the visitor while P2P setup is in flight if the connection is wanted"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if ctx.Err() != nil {\n    // cancellation, not a punch failure — do not count toward retry budgets\n    return ctx.Err()\n}","preventionTips":["Check ctx.Err() first when MakeHole returns an error to separate shutdown from failure","Keep parent deadlines longer than the nathole detect timeout","Do not stop frpc mid-visit if P2P setup is expected to finish"],"tags":["nat","context-cancellation","p2p","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}