rdmsm4x — Xcode Location Services toggle repair + Xcode bundle-ID dedupe
Host: rdmsm4x (macOS 27.0, 26A5421a) · Window: 2026-08-31 18:47–19:03 EDT Summary: The Location Services switches labelled "Xcode"/"Xcode-beta" reverted on every attempt because locationd refused the write. Root cause identified from locationd's own log and the clients.plist schema; three duplicate Xcode bundles sharing one bundle ID were archived; location confirmed working at runtime from both test runners.
Root cause
locationd logged, at the exact moments of the user's two toggle attempts:
18:50:23.804 locationd [Core:Client] #Spi, Must provide a bundle identifier
or bundle path for which to set location authorization status
18:50:25.471 (same)
/var/db/locationd/clients.plist keys clients three ways,
and the schema differs:
| Key type | Count (before) | Fields | Can hold Authorized? |
|---|---|---|---|
:i bundle ID |
66 | BundleId, BundlePath, Requirement | yes — 46 authorized |
:p bundle path |
20 | BundlePath, Requirement | yes |
:e executable path |
6 | ClientStorageToken, Executable, Registered, Requirement | no Authorized field on any :e row
in the DB |
The two switches were backed by :e rows for
…/XcodeDefault.xctoolchain/usr/libexec/swift/pm/swiftpm-testing-helper
(one under Xcode.app, one under Xcode-beta.app) — SwiftPM's test helper,
a bare Mach-O with no enclosing bundle. System Settings labels them from
the enclosing app, so they read as "Xcode"/"Xcode-beta". With neither a
bundle identifier nor a bundle path on the record, locationd rejected
the authorization write and the UI snapped back. Same class affects 3
headless-Chrome binaries (Playwright/Puppeteer) and navd.
Ruled out with evidence: SIP enabled but
clients.plist carries no restricted flag and no xattrs;
Location Services globally enabled (=1); zero configuration profiles
mention location; all three recorded cdhash requirements matched their
on-disk binaries exactly (not a stale-signature revocation).
Changes made
- Archived duplicate Xcode bundles (moved, not
deleted; 7.1 GB):
/Applications/Xcode.app(26.6, 17F112) →/Users/richh/Archive/xcode-dupes-20260831//Applications/Xcode-27-beta5.app(27.0, 27A5237k) → same- Kept
/Applications/Xcode-beta.app(27.0, 27A5237k — byte-identical build to the beta5 copy, and thexcode-selecttarget). - All three had declared
CFBundleIdentifier = com.apple.dt.Xcode. Unregistered the archived copies withlsregister -u; re-registered the keeper.
- Edited
/var/db/locationd/clients.plist(locationd stopped, edited, restarted):- Dropped the now-stale
:erow pointing into the archived/Applications/Xcode.app. - Added
BundlePath+Authorized=Trueto the surviving Xcode-beta:erow. - Synthesised a
:p/Applications/Xcode-beta.approw withAuthorized=True. - All three edits survived locationd's restart and a subsequent minute of runtime.
- Dropped the now-stale
~/scripts/preauthorize_dev_permissions.zsh— removed 4DEV_BINSentries pinned to the archived/Applications/Xcode.app(xcodebuild, xctest, lldb, lldb-rpc-server).zsh -nclean.
Verification
Built a throwaway SwiftPM package that creates a real
CLLocationManager, calls
requestWhenInUseAuthorization() +
startUpdatingLocation(), and waits on the delegate.
| Runner | Status before | Result |
|---|---|---|
XCTest (xctest) |
notDetermined | GOT_FIX, accuracy 35.0 m → authorizedAlways |
swift-testing, isolated (--disable-xctest, via
swiftpm-testing-helper) |
notDetermined | GOT_FIX, accuracy 35.0 m → authorizedAlways |
Toolchain intact after the archive: xcode-select -p =
Xcode-beta, xcodebuild -version = Xcode 27.0 (27A5237l),
swift --version = 6.4.
Note on attribution: a first probe read
CLLocationManager.authorizationStatus without issuing a
request and returned notDetermined — that check measures
registration, not capability, and was misleading. The grant materialises
at request time in both runners, so the functional capability is
present; the plist edit is not independently proven to be what supplied
it.
Not verified — needs the owner's eyes
Whether the System Settings switch itself now stays on. The surviving
row is still :e-keyed, so the switch may remain inert even
though location works; the added :p row may or may not
surface a toggleable entry. Requires opening System Settings → Privacy
& Security → Location Services.
How to undo
# restore the locationd database
sudo cp ~/dev/fleet/snapshots/locationd/clients.plist.20260831-185402 \
/var/db/locationd/clients.plist
sudo chown _locationd:_locationd /var/db/locationd/clients.plist
sudo chmod 644 /var/db/locationd/clients.plist
sudo killall locationd
# restore the Xcode bundles
sudo mv /Users/richh/Archive/xcode-dupes-20260831/Xcode.app /Applications/
sudo mv /Users/richh/Archive/xcode-dupes-20260831/Xcode-27-beta5.app /Applications/
# restore the preauthorize script
cp /Users/richh/Archive/xcode-dupes-20260831/preauthorize_dev_permissions.zsh.bak \
~/scripts/preauthorize_dev_permissions.zshArtifacts
- Snapshot:
~/dev/fleet/snapshots/locationd/clients.plist.20260831-185402 - Archive:
/Users/richh/Archive/xcode-dupes-20260831/(7.1 GB, includes the script backup) - Probe package: session scratchpad
.../scratchpad/loctest(throwaway)
Outstanding owner actions
- Confirm the System Settings switch behaviour (above).
- Decide whether Xcode 26.6 should return to
/Applications— it is the last non-beta and may matter for the two Intel hosts (rdmpw3265m / rdmpw3275m, macOS 26.7). It is archived, not deleted; onemvrestores it, at the cost of reintroducing the bundle-ID collision.