Skip to content

Comment-originated contacts cannot be messaged via API even after the contact replies (silent failure) #879

Description

@auroradream04

Summary

Contacts that originate from a Facebook comment cannot be messaged through the public API — even after the contact replies to the private reply and a standard 24-hour messaging window is open. The send returns 204, a message row is created, and nothing is delivered. sourceId is never populated on the row, which is the only way to tell from outside that it failed.

Sends to non-comment-origin contacts on the same inbox work reliably (22/22 in our sample), so this is specific to comment-originated contacts.

Cloud (app.chatbotx.io), Messenger channel, workspace API key.

Reproduction

Contact A (11630996004388864), inbox 11627001976487936. Times UTC, same thread:

time messageType senderType delivered? note
10:47:30 outgoing user yes (sourceId set) sent from Meta Business Suite, echoed in
10:47:50 incoming contact yes contact replies — 24h window opens
10:47:59 outgoing api no (sourceId null) POST /v1/contacts/id:.../messages → 204

Contact B (11630484688945152) is identical: contact sends "Is this free?" at 01:48:02, our API reply at 01:48:11 never delivers.

Sending manually from the ChatbotX inbox UI on the message thread also fails to deliver, so this is not specific to the public API.

Both contacts have a normal 17-digit contactInbox.sourceId, the same shape as contacts we message successfully. Their conversation.sourceId is <pageId>_<postId>.

Expected

Per Meta's Private Replies docs:

Only when a person responds to the private message can you continue the conversation within the 24-hour messaging window.

The contact responded, so a normal send should succeed.

Suspected cause

apps/worker/src/integration/handlers/received-message.tsreceiveComment keys the conversation to the post:

const incomingContact: IncomingContact = {
  sourceId: commentData.fromId,
  sourceConversationId: commentData.postId,
}

apps/worker/src/chat/handlers/send-message.ts then forwards that to the channel handler:

contact: { ...contactInbox, sourceConversationId: conversation.sourceId }

So a send resolving the comment conversation hands the channel a post id where a working contact supplies a message thread id. (The messenger channel implementation isn't in this repo, so I couldn't verify past this point.)

Possibly compounded by the assumption on the line above it:

// `from.id` is the commenter's ID (PSID for Messenger, ...)

Meta treats IDs across surfaces as not interchangeable — hence the ID Matching API. If a comment's from.id is not the messaging PSID for that Page, storing it as contactInbox.sourceId would produce exactly this: a well-formed id the Send API rejects.

Secondary issue: the failure is invisible to API consumers

send-message.ts emits message:failed internally, but nothing is persisted on the message row and the public API exposes no delivery status. From outside, a dead message is indistinguishable from a delivered one except by inferring from sourceId: null. This is the same silent-failure shape described in #831.

Surfacing a delivery status on the message resource would let integrators detect this without guesswork.

Third issue: lastIncomingMessageAt ignores comments and attachment-only messages

received-message.ts:

if (incomingMessage.messageType !== "outgoing" &&
    (incomingMessage.type ?? "message") === "message") {
  tracking.lastIncomingMessageAt = message.createdAt

Comments never update it, and attachment-only messages appear not to either. Since the unreplied and lastInteractionMinutesAgo contact filters are built on that column, any integrator polling for "who is waiting on a reply" is blind to both. In our workspace 48/50 comment-origin contacts have lastIncomingMessageAt: null.

Impact

Comment-to-DM is our main lead source. Every one of those leads who engages gets a reply that is recorded, billed, and shown as sent — and never arrives. It is silent on every surface except the Facebook thread itself.

Happy to test any fix against a live workspace.

Metadata

Metadata

Labels

bugSomething isn't working as expected

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions