Skip to content

Fall back to AppleScript when a Private API attachment send fails (fixes silent attachment drop on macOS Tahoe) - #237

Open
Austin519 wants to merge 1 commit into
mautrix:masterfrom
Austin519:fix/tahoe-attachment-applescript-fallback
Open

Fall back to AppleScript when a Private API attachment send fails (fixes silent attachment drop on macOS Tahoe)#237
Austin519 wants to merge 1 commit into
mautrix:masterfrom
Austin519:fix/tahoe-attachment-applescript-fallback

Conversation

@Austin519

Copy link
Copy Markdown

Problem

On macOS Tahoe (26.x), sending an attachment from Matrix to iMessage via the BlueBubbles backend fails silently. Text messages and links still deliver (they use /api/v1/message/text), but photos/files never arrive.

The BlueBubbles Private API helper throws NSInvalidArgumentException on the attachment send. BlueBubbles returns it as an HTTP 500 body:

Request to /api/v1/message/attachment
Sending attachment "image.png" to any;-;+1XXXXXXXXXX
API Error: [500] Attachment Send Error -> NSInvalidArgumentException

Because apiPostAsFormData / apiRequest unmarshal the response body regardless of HTTP status and return nil, SendFile treats this as success with an empty GUID — so the message checkpoint is reported SUCCESS and the dropped attachment is invisible to the user.

Fix

SendFile now:

  1. Attempts the send with the normal method (private-api when it's enabled).
  2. Detects a failed Private API attachment send (non-2xx status, or an empty returned GUID) and falls back to AppleScript.
  3. Resolves the any pseudo-service before the AppleScript send. AppleScript can't target any (set targetService to 1st account whose service type = anyCan't make any into type constant. (-1700)), so DMs are resolved to their real service via ResolveIdentifier (iMessage vs SMS), and groups / lookup failures default to iMessage.
  4. Delivers the caption as a follow-up message for non-private-api sends (unchanged behavior for that path), guarded against an empty caption.

This is non-regressing: on platforms where the Private API attachment path works, nothing changes — the fallback only runs when the Private API send actually fails.

Testing

Verified on a live macOS Tahoe (26.5) + BlueBubbles 1.9.9 setup: Private API attachment sends return [500] NSInvalidArgumentException; an AppleScript attachment send with the resolved concrete-service GUID delivers (Delivered message from [You]; Attachments: 1), while any;-;… errors with -1700. Builds with ./build.sh (libheif tag).

On macOS Tahoe (26.x) the BlueBubbles Private API helper throws
NSInvalidArgumentException when sending an attachment, so photos/files sent
from Matrix are silently dropped while text still works (text uses a different
endpoint). The helper returns a non-2xx body rather than a transport error, so
apiPostAsFormData reports success with an empty GUID and the drop goes
unnoticed.

SendFile now detects a failed Private API attachment send (non-2xx status or
empty GUID) and retries via AppleScript. The AppleScript path can't target the
"any" pseudo-service that portal GUIDs use ("Can't make any into type
constant"), so resolve it to a concrete service first (ResolveIdentifier for
DMs, iMessage for groups / on lookup failure). Non-private-api sends still
deliver the caption as a follow-up message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant