Case-ID: 17935956
In the NetworkExtension framework, for the NETransparentProxyProvider and NEDNSProxyProvider classes: when calling the open func writeDatagrams(_ datagrams: [Data], sentBy remoteEndpoints: [NWEndpoint]) async throwsin the NEDNSProxyProvider class, and the open func write(_ data: Data, withCompletionHandler completionHandler: @escaping @Sendable ((any Error)?) -> Void)in the NETransparentProxyProvider class, errors such as "The operation could not be completed because the flow is not connected" and "Error Domain=NEAppProxyFlowErrorDomain Code=1 "The operation could not be completed because the flow is not connected"" occur.
Once this issue arises, if it occurs in the NEDNSProxyProvider, the entire system's DNS will fail to function properly; if it occurs in the NETransparentProxyProvider, the entire network will become unavailable.
Thanks for those additional answers.
I understand it refers to the scenario: “You have an existing flow object …”
OK. The error you’re getting is "NEAppProxyFlowErrorDomain" / 1. That’s a bit confusing because the error domain string doesn’t match the error domain identifier. In fact, the identifier is NEAppProxyErrorDomain:
print(NEAppProxyErrorDomain)
// -> NEAppProxyFlowErrorDomain
So, code 1 corresponds to NEAppProxyFlowErrorNotConnected, which is documented to mean:
The flow is not fully opened.
However, you’re sure that the flow was fully open, so it’s not that simple.
I did some digging and it seems that this error is caused by you attempting to write when the write side of the flow is closed. There’s a couple of ways that might happen:
- If you write to the flow before the open is complete. Or at least I think that’s the case. I wasn’t able to be 100% sure about that, and I declined to research further because we already know that this isn’t relevant to your issue.
- If you close the flow by calling
closeWriteWithError(_:). - If the other end of the flow closes.
Now, it’s seems unlikely that you’re calling closeWriteWithError(_:), but I recommend that you double check that. Specifically:
- Add a log point to any part of your code that calls
closeWriteWithError(_:). Use the system log for this, not any custom logging. See Your Friend the System Log for more info about the system log. - And another log point to your code when it sees the specific error we’re talking about here.
- When you next see the problem, trigger a sysdiagnose log. This will capture a snapshot of the system log.
- Look in that snapshot to confirm that you haven’t accidentally closed the flow you’re trying to write to.
Note I talk more about this general idea in Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem.
If you run through this process and confirm that you’ve not closed the flow then the next step is to file a bug about this. Attach your sysdiagnose log to that bug and note the timestamp of the first time you saw the error, that is, the timestamp of the log point from step 3. Once you’re done, post your bug number here.
Ideally you would do this on a Mac with extra NE logging enabled, per the VPN (Network Extension) for macOS instructions on Bug Reporting > Profiles and Logs. But this isn’t an absolute requirement. If you can only get a normal sysdiagnose log taken shortly after seeing the problem then it’s worth filing a bug with just that.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"