What breaks when two people react to the same close checklist item?
Nothing breaks mechanically — Slack allows multiple users to add the same reaction to one message, and reactions.get returns all of them in a single users array with an accurate count. What breaks is an assumption: if a workflow expects exactly one specific person to sign off, it can't tell from the reaction alone which of several reactors was the one who mattered.
Part of the finance integrations guide.
| Symptom | A checklist item shows signed off, but it's unclear which of several people actually meant to approve it |
|---|---|
| Root cause | reactions.get's users array lists everyone who reacted, with no field marking who was authoritative |
| Not a bug | Slack correctly dedupes — the same user reacting twice returns already_reacted, not a duplicate entry |
| Real risk | A teammate reacting out of acknowledgment, not authority, can look identical to the responsible party's sign-off |
| Where this shows up | reactions.get on any message multiple people have reacted to |
What Slack actually does with a duplicate reaction
Slack's own documentation for reactions.add is specific about what counts as a duplicate: the already_reacted error fires for "the specified item already has the user/reaction combination" — meaning one user reacting twice with the same emoji is rejected, but two different users reacting with the same emoji to the same message is not a duplicate at all. Both are valid, independent reactions, and reactions.get's users array lists both.
Where the assumption breaks
A close checklist item like "AR aging reviewed" might reasonably be signed off by the AR lead specifically — not by whoever in the channel happens to react first. If a colleague reacts to acknowledge they've seen the item, or out of habit, that reaction is indistinguishable in the API response from the AR lead's actual sign-off. reactions.get returns both users in the same array with no role or authority field attached to either.
How to design around it
If a specific person's sign-off is what matters, check the users array for that specific user's Slack ID rather than just checking whether the reaction exists at all. A checklist item isn't "signed off" because someone reacted — it's signed off because the responsible person's ID appears in that item's users list for the agreed emoji. Anyone else's reaction on the same item is just visibility, not authority.
Next step
Map the finance workflow with the most exposure and prove the automation path.
Bring the invoice, contract, payment reconciliation, or customer finance workflow you have to defend at audit. Loopfour can map the trigger, controls, integrations, and approval loop.
Worked example
One checkmark, two reactors, one authoritative
A close checklist item, "Intercompany eliminations posted," is owned by the controller. A staff accountant, cc'd on the thread, reacts with a checkmark out of general acknowledgment thirty seconds after the message posts. Twenty minutes later the controller actually finishes the elimination entries and reacts with the same checkmark. reactions.get now returns { name: "white_check_mark", count: 2, users: ["U_STAFF", "U_CONTROLLER"] }. A workflow checking only "is count > 0" would have marked this item done thirty seconds after posting — before the work was actually finished. Checking for U_CONTROLLER specifically in the users array is what makes the sign-off mean what it's supposed to mean.
Frequently Asked Questions
Sources
Related
How-to
What should be on a month-end close checklist?
A complete close checklist covers subledger lockout, bank and balance-sheet reconciliations, accrual entries, intercompany revaluation and elimination if applicable, inventory review if applicable, consolidated review, and period lock. Each task should have a clear owner and a place in the dependency order, not just a due date.
Read moreTopic
Integrations
Every finance automation vendor publishes an integrations page: a grid of logos, a claim of "seamless" connectivity, and not much else. That page answers a marketing question — does this vendor touch…
Read moreHow-to
How do I set up interactive Slack approval buttons for invoice approval?
Post the invoice as a message with an interactive button block, then respond to the click by opening a modal with the trigger_id Slack sends in the interaction payload — within three seconds, before any lookup or validation. Loopfour's Slack integration supports this through sendMessage (with blocks) and openModal, but the modal call has to happen first, not last.
Read moreHow-to
How do I track close checklist sign-off using Slack reactions?
Post each close checklist item as its own message, then have the responsible person react to it with an agreed emoji to signal sign-off. Loopfour's Slack integration reads that back via reactions.get, which returns a users array naming who reacted — but Slack's own docs warn that array can be incomplete, so treat it as a strong signal, not a guaranteed audit trail.
Read more