From ac8ff6f97d5f72d1ba05583f937dd9f07fc7b722 Mon Sep 17 00:00:00 2001 From: Micah Alpern Date: Sun, 13 Sep 2026 09:37:40 -0700 Subject: [PATCH] Prevent preference defaults startup crash --- .../Services/Configuration/PreferencesService.swift | 8 +++++++- Tests/KeyPathTests/PreferencesServiceTests.swift | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/KeyPathAppKit/Services/Configuration/PreferencesService.swift b/Sources/KeyPathAppKit/Services/Configuration/PreferencesService.swift index 0713694ad..f6050b51b 100644 --- a/Sources/KeyPathAppKit/Services/Configuration/PreferencesService.swift +++ b/Sources/KeyPathAppKit/Services/Configuration/PreferencesService.swift @@ -179,7 +179,13 @@ final class PreferencesService: @unchecked Sendable { static var canonicalDefaults: UserDefaults { TestEnvironment.isRunningTests ? .standard - : UserDefaults(suiteName: "com.keypath.KeyPath")! + : canonicalDefaults(using: UserDefaults(suiteName: "com.keypath.KeyPath")) + } + + /// The suite can be unavailable during early app launch. Preferences must + /// still initialize so launchd does not restart the app in a crash loop. + static func canonicalDefaults(using suiteDefaults: UserDefaults?) -> UserDefaults { + suiteDefaults ?? .standard } static let leaderKeyPreferenceKey = "KeyPath.LeaderKey.Preference" diff --git a/Tests/KeyPathTests/PreferencesServiceTests.swift b/Tests/KeyPathTests/PreferencesServiceTests.swift index 3b8b830e7..c1b5ad853 100644 --- a/Tests/KeyPathTests/PreferencesServiceTests.swift +++ b/Tests/KeyPathTests/PreferencesServiceTests.swift @@ -3,6 +3,16 @@ import XCTest @MainActor final class PreferencesServiceTests: XCTestCase { + func testCanonicalDefaultsFallsBackToStandardWhenSuiteIsUnavailable() { + let key = "PreferencesServiceTests.canonicalDefaultsFallback" + let defaults = PreferencesService.canonicalDefaults(using: nil) + defer { UserDefaults.standard.removeObject(forKey: key) } + + defaults.set(true, forKey: key) + + XCTAssertTrue(UserDefaults.standard.bool(forKey: key)) + } + // MARK: - Port Validation func testIsValidPort_AcceptsUserPorts() {