{"record":{"id":"e9f190f7d16a46f1","repo":"tailscale/tailscale","slug":"seticmperrimmunity-getting-syscallconn-failed-v","errorCode":null,"errorMessage":"SetICMPErrImmunity: getting SyscallConn failed: %v","messagePattern":"SetICMPErrImmunity: getting SyscallConn failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"net/sockopts/sockopts_windows.go","lineNumber":30,"sourceCode":"\n\t\"golang.org/x/sys/windows\"\n\t\"tailscale.com/types/nettype\"\n)\n\n// SetICMPErrImmunity sets socket options on pconn to prevent ICMP reception,\n// e.g. ICMP Port Unreachable, from surfacing as a syscall error.\n//\n// If pconn is not a [*net.UDPConn], then SetICMPErrImmunity is no-op.\nfunc SetICMPErrImmunity(pconn nettype.PacketConn) error {\n\tc, ok := pconn.(*net.UDPConn)\n\tif !ok {\n\t\t// not a UDP connection; nothing to do\n\t\treturn nil\n\t}\n\n\tsysConn, err := c.SyscallConn()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"SetICMPErrImmunity: getting SyscallConn failed: %v\", err)\n\t}\n\n\t// Similar to https://github.com/golang/go/issues/5834 (which involved\n\t// WSAECONNRESET), Windows can return a WSAENETRESET error, even on UDP\n\t// reads. Disable this.\n\tconst SIO_UDP_NETRESET = windows.IOC_IN | windows.IOC_VENDOR | 15\n\n\tvar ioctlErr error\n\terr = sysConn.Control(func(fd uintptr) {\n\t\tret := uint32(0)\n\t\tflag := uint32(0)\n\t\tsize := uint32(unsafe.Sizeof(flag))\n\t\tioctlErr = windows.WSAIoctl(\n\t\t\twindows.Handle(fd),\n\t\t\tSIO_UDP_NETRESET,               // iocc\n\t\t\t(*byte)(unsafe.Pointer(&flag)), // inbuf\n\t\t\tsize,                           // cbif\n\t\t\tnil,                            // outbuf","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/net/sockopts/sockopts_windows.go#L12-L48","documentation":"Windows-only helper that makes a UDP socket immune to WSAENETRESET / ICMP-unreachable errors (it issues the SIO_UDP_NETRESET ioctl). This variant means (*net.UDPConn).SyscallConn() itself failed, which for a live UDPConn essentially only happens when the connection is already closed or in a broken state. Non-UDP conns are silently skipped, so reaching this error implies the conn was a *net.UDPConn.","triggerScenarios":"Calling SetICMPErrImmunity(pconn) on a *net.UDPConn whose Close already ran (close-then-configure race in socket setup), producing a SyscallConn error that sockopts_windows.go:30 wraps with the function name.","commonSituations":"Socket setup code that configures options concurrently with teardown (e.g. wireguard-style bind rebinds); double-close of the socket before the ioctl; wrapping the UDPConn so the type assertion still passes but the underlying conn is dead.","solutions":["Reorder so SetICMPErrImmunity runs immediately after creating the UDPConn, before any goroutine that could close it","Audit for double Close of the same socket","Treat the returned error as fatal for that socket and recreate it, rather than continuing without ICMP immunity"],"exampleFix":"// before\nconn, _ := net.ListenPacket(\"udp\", \":0\")\ngo closeOnRebind(conn) // may Close concurrently\nSetICMPErrImmunity(conn.(*net.UDPConn)) // SyscallConn fails if closed\n\n// after\nuc := conn.(*net.UDPConn)\nif err := sockopts.SetICMPErrImmunity(uc); err != nil {\n    uc.Close() // socket unusable; recreate\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := sockopts.SetICMPErrImmunity(conn); err != nil {\n    conn.Close() // socket is in a broken state; recreate it\n    return fmt.Errorf(\"udp setup failed: %w\", err)\n}","preventionTips":["Call SetICMPErrImmunity synchronously right after creating the UDPConn, before exposing it to any goroutine that may close it","Keep single ownership of the socket so Close cannot race setup"],"tags":["windows","go","udp","winsock","sockopts"],"backgroundTag":"winsock-ioctl-failed","analyzedSha":"6e0912f97994f927632b34ae9e63b53d6516a6ac","analyzedAt":"2026-08-18T08:17:25.280Z","contentChangedAt":"2026-08-18T08:17:25.280Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}