CLLocationManager stuck at notDetermined in a signed LaunchAgent on macOS 14

Environment

  • macOS 14+ (Sonoma), Apple Silicon
  • Background LaunchAgent installed at /Applications/<my-app>.app, launched by a plist in /Library/LaunchAgents. LSUIElement = true (no Dock icon).
  • Signed with a Developer ID Application certificate, hardened runtime, secure timestamp. Notarized. No provisioning profile embedded.
  • Distributed outside the App Store (signed .pkg installer).

Info.plist keys present in the installed bundle:

  • NSLocationUsageDescription
  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysAndWhenInUseUsageDescription

Entitlements file: empty <dict/> (I removed com.apple.developer.* entitlements because they require a provisioning profile that Developer ID distribution cannot ship.)

What I need CoreWLAN's scanForNetworks(withSSID:) returns entries with nil ssid / nil bssid on macOS 14+ unless the process has Location authorization. I'm trying to obtain that authorization from the LaunchAgent so I can populate SSID/BSSID for a connectivity report.

What I'm doing

  • Instantiating CLLocationManager on the main thread (verified via Thread.isMainThread) from an NSApplication.shared.run() runloop.
  • Setting a CLLocationManagerDelegate.
  • Calling requestWhenInUseAuthorization(), requestAlwaysAuthorization(), and startUpdatingLocation().

Observed behavior

  • No authorization prompt is ever displayed.
  • authorizationStatus stays at .notDetermined across launches.
  • locationManager(_:didFailWithError:) fires with kCLErrorDomain error 1 (kCLErrorDenied).
  • System Settings → Privacy & Security → Location Services lists the app and its toggle can be flipped ON, yet the process still reads authorizationStatus == .notDetermined immediately after and on subsequent launches.
  • locationd logs (Console) around the same time show: "#Warning #ClientResolution the passed keyPath is not registered. Resolving to #nullCKP"

Things I've already tried

  • Verified Info.plist keys are embedded in the installed bundle (defaults read /Applications/<app>/Contents/Info.plist).
  • Verified codesign is valid and entitlements are preserved on install (codesign -d --entitlements - /Applications/<app>).
  • tccutil reset All <bundle-id> and full reboot.
  • Uninstall + reinstall.
  • Toggling Location Services OFF and back ON, both globally and per-app.
  • Ensuring all CLLocationManager interaction runs on the main thread.
  • Verified CLLocationManager.locationServicesEnabled() returns true.

Questions

  1. Is a Developer-ID-signed LaunchAgent (LSUIElement=true, no Dock icon) supposed to be able to trigger the standard Location prompt on macOS 14+, or is a foreground/UI process required to establish initial authorization?
  2. What does the locationd "keyPath is not registered / Resolving to #nullCKP" message indicate, and how do I diagnose which registration is missing?
  3. Is there an entitlement or Info.plist key I'm still missing for Developer-ID-distributed background agents to be recognized by locationd?
  4. Given that the Settings toggle appears to be ON but authorizationStatus still reports .notDetermined to the running process, is there a bundle identity / code-signing check I can run to confirm locationd is looking at the same identity Settings is showing?

Any pointers appreciated - happy to share codesign output, sample entitlements plist, or the full locationd log excerpt on request.

CLLocationManager stuck at notDetermined in a signed LaunchAgent on macOS 14
 
 
Q