Fix Sendable warning in AppleMailError by dropping the NSDictionary payload

appleScriptError carried the raw NSDictionary from NSAppleScript's error
out-param, which isn't Sendable and got flagged once the type crossed an
async boundary. Extract just the two fields actually used (errorNumber,
errorMessage) into plain Int/String instead.
This commit is contained in:
2026-08-19 13:53:06 +02:00
parent 4064851a3d
commit cf82720b88
2 changed files with 13 additions and 25 deletions
+10 -10
View File
@@ -37,9 +37,9 @@ struct MailSearchResult: Sendable, Equatable {
let attachmentCount: String let attachmentCount: String
} }
enum AppleMailError: Error { enum AppleMailError: Error, Sendable {
case scriptNotCompiled case scriptNotCompiled
case appleScriptError(NSDictionary) case appleScriptError(number: Int, message: String)
} }
@Observable @Observable
@@ -320,7 +320,9 @@ final class AppleMailService {
var errorDict: NSDictionary? var errorDict: NSDictionary?
let result = script.executeAppleEvent(event, error: &errorDict) let result = script.executeAppleEvent(event, error: &errorDict)
if let errorDict { if let errorDict {
continuation.resume(returning: .failure(.appleScriptError(errorDict))) let number = (errorDict[NSAppleScript.errorNumber] as? Int) ?? 0
let message = (errorDict[NSAppleScript.errorMessage] as? String) ?? "Unknown error"
continuation.resume(returning: .failure(.appleScriptError(number: number, message: message)))
} else { } else {
continuation.resume(returning: .success(result)) continuation.resume(returning: .success(result))
} }
@@ -358,9 +360,7 @@ final class AppleMailService {
return results return results
} }
nonisolated static func mapAppleScriptError(_ errorInfo: NSDictionary) -> String { nonisolated static func mapAppleScriptError(number: Int, message: String) -> String {
let number = (errorInfo[NSAppleScript.errorNumber] as? Int) ?? 0
let message = (errorInfo[NSAppleScript.errorMessage] as? String) ?? "Unknown error"
switch number { switch number {
case -1743: case -1743:
return "Confab is not authorized to control Mail.app. Grant access in System Settings \u{2192} Privacy & Security \u{2192} Automation \u{2192} Confab \u{2192} Mail, then try again." return "Confab is not authorized to control Mail.app. Grant access in System Settings \u{2192} Privacy & Security \u{2192} Automation \u{2192} Confab \u{2192} Mail, then try again."
@@ -375,8 +375,8 @@ final class AppleMailService {
switch error { switch error {
case .scriptNotCompiled: case .scriptNotCompiled:
return ["error": "Mail integration failed to initialize (AppleScript compile error)."] return ["error": "Mail integration failed to initialize (AppleScript compile error)."]
case .appleScriptError(let dict): case .appleScriptError(let number, let message):
return ["error": mapAppleScriptError(dict)] return ["error": mapAppleScriptError(number: number, message: message)]
} }
} }
@@ -629,8 +629,8 @@ final class AppleMailService {
switch error { switch error {
case .scriptNotCompiled: case .scriptNotCompiled:
message = "Mail integration failed to initialize (AppleScript compile error)." message = "Mail integration failed to initialize (AppleScript compile error)."
case .appleScriptError(let dict): case .appleScriptError(let number, let msg):
message = Self.mapAppleScriptError(dict) message = Self.mapAppleScriptError(number: number, message: msg)
} }
return .failure(NSError(domain: "AppleMailService", code: 1, userInfo: [NSLocalizedDescriptionKey: message])) return .failure(NSError(domain: "AppleMailService", code: 1, userInfo: [NSLocalizedDescriptionKey: message]))
} }
+3 -15
View File
@@ -85,32 +85,20 @@ struct AppleMailServiceTests {
@Test("mapAppleScriptError maps -1743 to an Automation-permission message") @Test("mapAppleScriptError maps -1743 to an Automation-permission message")
func mapsNotAuthorizedError() { func mapsNotAuthorizedError() {
let dict: NSDictionary = [ let message = AppleMailService.mapAppleScriptError(number: -1743, message: "Not authorized")
NSAppleScript.errorNumber: -1743,
NSAppleScript.errorMessage: "Not authorized"
]
let message = AppleMailService.mapAppleScriptError(dict)
#expect(message.contains("not authorized")) #expect(message.contains("not authorized"))
#expect(message.contains("Automation")) #expect(message.contains("Automation"))
} }
@Test("mapAppleScriptError maps -600 to a Mail-not-available message") @Test("mapAppleScriptError maps -600 to a Mail-not-available message")
func mapsApplicationNotRunningError() { func mapsApplicationNotRunningError() {
let dict: NSDictionary = [ let message = AppleMailService.mapAppleScriptError(number: -600, message: "Application isn't running")
NSAppleScript.errorNumber: -600,
NSAppleScript.errorMessage: "Application isn't running"
]
let message = AppleMailService.mapAppleScriptError(dict)
#expect(message.contains("not available")) #expect(message.contains("not available"))
} }
@Test("mapAppleScriptError falls back to a generic formatted message for unknown error numbers") @Test("mapAppleScriptError falls back to a generic formatted message for unknown error numbers")
func mapsGenericError() { func mapsGenericError() {
let dict: NSDictionary = [ let message = AppleMailService.mapAppleScriptError(number: -1234, message: "Something odd happened")
NSAppleScript.errorNumber: -1234,
NSAppleScript.errorMessage: "Something odd happened"
]
let message = AppleMailService.mapAppleScriptError(dict)
#expect(message.contains("-1234")) #expect(message.contains("-1234"))
#expect(message.contains("Something odd happened")) #expect(message.contains("Something odd happened"))
} }