Skip to content

Add missing message attachments from attributed body - #815

Open
qayshp wants to merge 1 commit into
BlueBubblesApp:developmentfrom
qayshp:codex/hydrate-attributed-body-attachments
Open

Add missing message attachments from attributed body#815
qayshp wants to merge 1 commit into
BlueBubblesApp:developmentfrom
qayshp:codex/hydrate-attributed-body-attachments

Conversation

@qayshp

@qayshp qayshp commented Jun 25, 2026

Copy link
Copy Markdown

Disclosure: This change was prepared with Codex assistance.

Summary

This adds missing message attachments from file-transfer GUIDs found in attributedBody when those attachments were not loaded through the normal attachment join.

Observed impact

This was seen while using BlueBubbles Server 1.9.9 as the local backend for a self-hosted Beeper iMessage bridge on macOS Sequoia 15.7.7 (24G720). In an iMessage group chat, image messages were not loading in Beeper because the BlueBubbles message/chat APIs returned attachments: [] for affected messages.

For the affected message, the attachment GUID was still present in attributedBody under __kIMFileTransferGUIDAttributeName, and BlueBubbles could resolve that GUID through the existing attachment endpoint. The media existed, but API consumers did not see it in the message payload.

Related Issue

Fixes #816.

macOS version comparison

A comparison against a newer macOS sample (26.5.1, build 25F80) did not reproduce the missing-join shape: the same class of inbound group-chat image message had both a message_attachment_join row and a file-transfer GUID in attributedBody, and BlueBubbles returned the attachment through HTTP and Socket.IO.

The affected macOS 15.7.7 sample differed by retaining the resolvable file-transfer GUID in attributedBody while omitting the normal message_attachment_join relationship. This change handles that recoverable fallback case and is a no-op when the join already loads the attachment.

Changes

  • When attachments are requested, add any attachments referenced by file-transfer GUIDs in attributedBody that are not already present on the message.
  • Reuse the existing getAttachment() lookup so attachment GUID handling stays in one place.
  • Avoid adding duplicates when attachments were already loaded through message_attachment_join.

Tested

Tested against the local BlueBubbles data on the same Mac where the Beeper bridge issue was reproduced.

  • Baseline installed BlueBubbles 1.9.9 on 127.0.0.1:1234: the known affected message returned attachments: [].
  • Patched BlueBubbles server from this branch: the same direct message API call returned the expected JPEG attachment.
  • Patched chat pagination API for the affected group chat: the known message was present and returned the same expected attachment.
  • Patched Socket.IO message query and live event paths also returned the expected attachment for the affected message shape.
  • Replaced the local BlueBubbles app with the patched build and confirmed the self-hosted Beeper sh-imessage bridge queried the patched BlueBubbles endpoint directly.

Validation commands run:

  • git diff --check
  • npm ci --ignore-scripts
  • ../../node_modules/.bin/eslint --ext=ts src/server/databases/imessage/index.ts --quiet
  • npm run build from packages/server

Full npm run lint -- --quiet still fails on unrelated pre-existing lint errors outside this change.

@qayshp
qayshp force-pushed the codex/hydrate-attributed-body-attachments branch from 9ef2d40 to 3888691 Compare June 25, 2026 21:08
@qayshp qayshp changed the title [codex] Hydrate message attachments from attributed body [codex] Add missing message attachments from attributed body Jun 25, 2026
@qayshp
qayshp force-pushed the codex/hydrate-attributed-body-attachments branch 2 times, most recently from 02239c7 to dfafb96 Compare June 25, 2026 21:23
@qayshp
qayshp marked this pull request as ready for review June 25, 2026 21:30
@qayshp qayshp changed the title [codex] Add missing message attachments from attributed body Add missing message attachments from attributed body Jun 26, 2026
@qayshp
qayshp force-pushed the codex/hydrate-attributed-body-attachments branch from dfafb96 to 8793475 Compare July 4, 2026 20:23
When attachments are requested, add any attachments referenced by file-transfer GUIDs in attributedBody that are not already present on the message. Resolve those GUIDs through the existing attachment lookup.

This fixes affected group-chat image messages observed with BlueBubbles Server 1.9.9 backing a self-hosted Beeper iMessage bridge on macOS Sequoia 15.7.7, where the message/chat APIs returned attachments: [] even though the attachment GUID was present in attributedBody and resolvable by the attachment API.
@qayshp
qayshp force-pushed the codex/hydrate-attributed-body-attachments branch from 8793475 to 386c756 Compare July 15, 2026 19:59
@qayshp
qayshp changed the base branch from master to development July 15, 2026 19:59
@zlshames

Copy link
Copy Markdown
Member

I got a question. Do you know for sure if the message quite literally didn't have a corresponding message_attachment_join entries (maybe attachment_message_join, i forget)? Like is this a bug with how we fetch attachments related to messages? Or did the DB literally not have the relationship in it, so BB didn't see it either? The distinction is important.

@qayshp

qayshp commented Jul 19, 2026

Copy link
Copy Markdown
Author

Yes. For the messages I tested, the relationships were missing from the database itself. I checked ~/Library/Messages/chat.db directly:

SELECT COUNT(*)
FROM message_attachment_join
WHERE message_id = <affected message ROWID>;

That returned 0. The messages had __kIMFileTransferGUIDAttributeName in attributedBody and cache_has_attachments = 0. The GUIDs still resolved through BlueBubbles' existing attachment lookup, and I was able to download the attachments successfully.

I also confirmed that BlueBubbles maps Message.attachments to message_attachment_join using message_id and attachment_id. This was not TypeORM failing to load existing relationships. There were no join rows to load.

For comparison, an equivalent inbound group image on macOS 26.5.1 had both the message_attachment_join row and the file-transfer GUID in attributedBody. This PR adds a fallback for the missing relationships I saw on this macOS 15.7.7 machine, while doing nothing when the normal joins are present.

I do not know why this machine's Messages database has this shape. It could be related to the macOS version, the database's history or migration state, or something specific to this machine. I also do not know why other users have not reported the same issue. This fixes the issue for me and should not break anything for others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Message/chat APIs can omit attachments referenced only in attributedBody

2 participants