URLSession on watchOS never fails over to watch's own Wi-Fi when paired iPhone has Bluetooth but no internet (-1200)

This thread has been locked by a moderator; it no longer accepts new replies.

We develop a healthcare emergency-alerting app with a native watchOS companion app. We've hit a network routing issue on watchOS that we cannot work around with any public API, and it breaks a safety-critical flow (triggering an emergency alarm from the watch).

Environment

  • watchOS 26.5 on Apple Watch SE3, paired with iPhone SE on iOS 26.5
  • Watch app deployment target: watchOS 9.0
  • Plain URLSession (async/await), default configuration plus waitsForConnectivity = false, allowsExpensiveNetworkAccess = true, allowsConstrainedNetworkAccess = true
  • HTTPS to our own backend (valid public TLS certificate, no pinning)

Steps to reproduce

  1. Pair the watch with the iPhone. Both on the same known Wi-Fi network.
  2. On the iPhone: turn OFF Wi-Fi and cellular data. Keep Bluetooth ON.
  3. The watch remains connected to its known Wi-Fi network (or would be, if the system brought the radio up).
  4. Trigger any HTTPS request from the watch app (foreground).

Expected

Since the companion iPhone has no internet, the watch should satisfy the request over its own Wi-Fi.

Actual

The request is routed through the companion link (ipsec1, "companion preference: prefer" in the logs) and fails after the TLS handshake dies inside the tunnel:

Error Domain=NSURLErrorDomain Code=-1200
"An SSL error has occurred and a secure connection to the server cannot be made."
_kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9816 (errSSLClosedNoNotify)

The watch never fails over to its own Wi-Fi, no matter how many times we retry or how long we wait. The same request succeeds within seconds if the user disables Bluetooth on the iPhone (watch then joins Wi-Fi directly), or restores the iPhone's internet.

What we already tried

  • waitsForConnectivity = true doesn't help; a path exists (the tunnel), it just doesn't work.
  • Fresh URLSession per retry, backoff retries still routed via the tunnel.
  • Per TN3135 we understand low-level networking is not available to a normal app: we prototyped NWConnection with prohibitedInterfaceTypes = [.other], and indeed on device NWPathMonitor stays .unsatisfied even when the watch has working Wi-Fi, exactly as TN3135 describes. So Network framework is not an escape hatch for us, and we are not looking to abuse the audio-streaming/CallKit carve-outs.

Questions

  1. Is the companion-preferred routing supposed to fail over to the watch's own Wi-Fi when the iPhone is reachable over Bluetooth but has no internet? If yes, on what timescale, and is there anything an app can do to help the system notice the dead path sooner?
  2. Is there ANY supported way for a foreground watchOS app to express "do not use the companion link for this request"? We found only the private _companionProxyPreference SPI, which we obviously can't ship.
  3. If the answer to both is "no", what is the recommended pattern for safety-critical requests in this state is failing fast and instructing the user to disable iPhone Bluetooth really the intended UX?

Related earlier reports of the same behavior: https://developer.apple.com/forums/thread/759321 https://developer.apple.com/forums/thread/107964

Answered by DTS Engineer in 892101022

Let’s focus this discussion on your other thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Let’s focus this discussion on your other thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

URLSession on watchOS never fails over to watch's own Wi-Fi when paired iPhone has Bluetooth but no internet (-1200)
 
 
Q