Sending Slack Notifications from Make Without Coding Or Regret
1. Building the Slack module when you are not using code
First time I tried sending a Slack notification from Make, I assumed it’d be like Zapier. Drop a Slack module, map in some fields, done. Nope. The message never sent and everything else in the scenario ran flawlessly. At first I thought Slack rate-limited it. Three scenario runs later and zero errors, zero notifications — the module just kind of… no-ops if you forget one required input deep inside the options menu. It’s the equivalent of clicking “send” on Gmail with no recipient and Gmail just smiling at you.
In Make, the basic Slack setup looks easy: “Create a Message” module, connect a Slack connection, pick a channel. But buried inside: several optional-looking-but-required-in-context fields. For example, if you use formatting or quotes in the body text, you must also set the message type to “custom text” — or it silently fails. In the module doc it says “text” is default. It’s not, apparently. Not when rich formatting tags are involved.
Another issue: if you try to map the channel
dynamically using a previous module’s output (say from an Airtable “Slack Channel” field), Make does not validate the format. And Slack’s format is strict. If it’s a private channel, Make won’t auto-complete it, and it will still try to send — but Slack rejects it.
I eventually discovered I had selected a custom bot user as the sender. One that… did not have permission in that workspace anymore. The connection authenticated fine. But the bot was disabled in Slack. Again, Make won’t warn you. Nothing in the logs. It’s just like: “Here you go, you asked me to send a message, I tried.” No warning, no status code, just silence.
2. Using Slack threads from Make without creating Slack chaos
This was a surprise. I assumed Slack threads could be created by referencing ts
(timestamp) values from a previous step. And you can. But if you send a message using Make and immediately try to reference message.ts
for a thread, there’s a decent chance it won’t be available fast enough.
I had a scenario where a lead was added to Airtable, and I wanted to post a summary in Slack, then reply to that summary with a series of follow-up status updates — all as threaded messages. In Make’s run log, everything looked fine. But in Slack, all replies landed as standalone posts. Four minutes into debugging, I realized I was referencing the ts
field from a Create a Message module without checking if the field was bundled in the output.
Turns out that on some configurations — like when using a webhook trigger going into Slack — the timestamp is not always returned. Especially when you use the bot method instead of the app token with full permissions. You need to manually enable the “Include full response” checkbox in the module’s settings, deep under the wrench icon. I still don’t know why that setting resets itself maybe every eighth time I edit the module — probably UI state caching going stale. But once you re-enable that, you get access to the full payload, including the message timestamp like:
{
"ok": true,
"channel": "C123XYZ",
"ts": "1712345678.000900",
...
}
After that value is available, you can reference it normally as the Thread Timestamp for the second Slack module. But honestly, it shouldn’t have to be this obscure.
3. Why triggers based on Airtable fields randomly stop working
I had a filtered view in Airtable called “Send to Slack” — only showing records with a status of “New Lead”. Make was set to watch that view and trigger a notification in Slack. First few days? Fine. Then, mid-week, nothing came through. The view was still there. The filter conditions hadn’t changed. I double-checked the Run History — batteries working, no errors, zero records found each trigger.
What actually happened: someone moved the filter in Airtable to include an added “Archived = false” flag upstream. Perfectly logical for the humans using the base. But that silently excluded all the rows from the view Make was watching. Make still watched the view — there’s no re-validation step — and considered it up to date. You don’t get a warning when a view returns no data. It’s just quiet again.
So if your Slack output dries up and you see zero data from Airtable, check the Airtable view logic, not just your filters. It’s an edge case but it hits more than once. Especially with shared bases where collaborators see “New Lead” and tweak filters thinking they’re helping.
4. Differences between Slack user mentions and user IDs
Slack does not behave the way you’d hope when handling mentions through automation. If you try to type @John
directly in a Make scenario, Slack won’t resolve it. You get a message with @John
as plain text and no real mention. This makes people ignore your messages. Even worse, if you copy a mention field from another Slack action and paste it, Slack might convert it visually — but the backend will reject it if the workspace doesn’t match the ID format.
Here’s what finally worked (after three Slack doc rabbit holes):
- Use the full Slack user ID format:
<@U0231ABC7>
- Pull it from the Slack user object (use a search module first)
- Don’t try to guess IDs — Slack user lists change depending on whether your bot is in the right channels
- Use plain mapping, avoid rich text — Slack’s parser is not smart about this
- Keep Slack modules authenticating via the same bot/app combo, or stuff breaks unpredictably
- Avoid using email addresses for mentions — even if Make offers it via Slack API, it only works if the user has shared email access with the app
The aha moment was realizing that even when I used a Slack search module to pull user data, it wouldn’t return results unless the Slack connection had visibility into all users in the workspace. It’s not just channel-specific — Slack bots may be scoped to less than you’d expect unless you check every permission box.
5. Avoiding duplicate Slack notifications using deduplication logic
The thing that finally made me lose it: Slack messages for the same Airtable record coming in repeatedly, like once an hour. I was using a scheduled Make scenario, running every 60 minutes, with a search step in Airtable checking for records with “Status = Needs Review.” I assumed Airtable search would avoid pulling the same records twice. Wrong. The step returned all matching rows on every run — unless a timestamp changed, those rows persisted.
So each time the scenario ran, I was sending the same message to Slack again. Eventually had to write a “Has Slack Notified?” checkbox field and update it programmatically after Slack completed the send.
The bug here: Make doesn’t auto-deduplicate search outputs. You need to implement your own guard. Airtable’s API returns the same rows over and over if no filter field changes. Filtering inside Make helps, but UI filtering doesn’t fully limit API results unless you specify a filterByFormula in Airtable itself.
One solution that held up:
- Add a “Slack Notified” single-select or checkbox field per record
- In your Make search, filter by records where Slack Notified is FALSE
- After sending the message, use an Update Record module to flip that field
This way, once a lead gets notified, it exits the search result set for future runs. If someone wants to trigger again, they can toggle the field manually. It’s human-traceable and decently robust — doesn’t rely on timestamps or scenario history.
6. Threaded Slack messages misfire if your app lacks chat write scopes
Here’s a non-obvious permission problem: your Make Slack connection might list “send messages” as an ability, but if the specific Slack app doesn’t include chat:write.public
scope, it won’t be able to post to certain channels unless the bot is already a member.
This is maddening because you get no Make error — the API call goes through, but Slack drops the message without processing. Once again, nothing in Make’s logs. You only notice because someone says, “Hey, the bot used to notify me” and it just stopped.
The fix: Go to api.slack.com, check the app config (not the bot user settings), confirm it has all the proper scopes. If not, regenerate token or re-auth the connection in Make. One thing I had to do on one workspace: re-install the Slack app entirely, then reconnect in Make using the new token. Painful, but after that thread replies and channel messages started appearing normally again.
7. Slack reply timestamps break if you don’t rate-limit your messages
Was running a series of Slack posts in a loop — initial message + 3 sequential follow-ups replying to it via thread. Instead of legit threading, half the replies landed outside the thread. Others didn’t show up at all. Weirdest part? Logs showed thread_ts
matched the original post.
What happened: Make executed the loop too fast. Faster than Slack could register the original message internally. So the first follow-up tried to thread to a message that didn’t exist yet, according to the API. No validation, Slack just posted it as a standalone reply.
Fixed it with a simple Make “sleep” module — added a 2-second delay between sending the original and the first threaded reply. That alone bumped up reliability massively. Had to increase to 3 seconds for channels with heavy previous message history (probably due to indexing latency?).
Also, I noticed that on high-volume Slack workspaces, if the thread base message includes any attachments, Slack registers the ts
slightly differently, and threading becomes flakier. A JSON preview confirmed this:
{
"ts": "1712345678.000100",
"blocks": [...],
"attachments": [...]
}
The attachment block seems to affect how fast Slack acknowledges the timestamp. I started stripping out attachments and replacing them with Markdown blocks instead — more stable, and slightly faster to generate in Make’s visual editor.