How a forgotten condition caused an infinite loop in Slack alerts

How a forgotten condition caused an infinite loop in Slack alerts

1. Why your Slack alert fired six times at 2 AM for one event

I had a scenario where one Airtable record update triggered a Slack alert… six times. All within the same minute. The scenario in Make looked fine. Airtable watched for a field change, filtered for status = “Done”, then posted to Slack. No cycles. No loops. Except that it turned into a loop from inside the Airtable module itself.

The issue? Airtable re-evaluates the entire list if any dependency shifts. I had an automation elsewhere that was syncing fields silently after a form update. It touched a non-watched field, but that retriggered the record timestamp. Since the Make module was filtering with an “updated since” timestamp as a trigger param (which is not visible in the UI unless you open the Advanced tab), it re-fired on the same record each time another automation touched it behind the scenes.

“We didn’t even see the Slack ping flood until someone wrote an ‘i guess this one’s REALLY done’ at 2:11 AM.”

This is one of those behavioral bugs that doesn’t log as a failure. No red modules. No warnings. It just worked… too many times.

2. Filtering logic in Make that looks smart but quietly fails

Make’s filters are either your best friend or a complete backstab. In one Slack notification workflow, I used a filter after an Airtable trigger: Status equals Done. Seems obvious. But what I missed was that Airtable text fields are case-sensitive when parsed via the Make connector. The triggering value was “done” (lowercase), because someone had typed it via a form entry synced through Zapier before Make saw it. So it failed the filter and never pinged Slack.

Worse? No error. The run triggers, filters, and ends early without logging a warning. You have to actually open the run history and inspect a green bubble with a red filter cross inside it to even notice something happened at all.

When I explicitly added lower(Status) equals done as an expression, it finally behaved. But seriously, who expects Airtable to send inconsistent casing depending on how the record was updated?

3. Handling empty fields that sometimes crash your Slack message JSON

This happened with a Slack message block I generated using a JSON text module that pulled in 4 fields from Airtable. One of them was a URL. On some records, the URL wasn’t filled in — and instead of skipping it, Make tried to insert an empty string into the JSON payload, like so:

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "Check the record:  "
  }
}

Slack’s API doesn’t like improperly formatted blocks. That blank link broke everything. The entire Slack module failed silently because it was wrapped inside a larger conditional branch with a fallback. I didn’t even know something failed until someone saw a completely blank Slack thread where the message was supposed to be.

The fix wasn’t adding a conditional branch — it was cleaning the JSON inline. I had to do this:

{{ if(contains(URL; "http") ; concat("Check the record: ", URL) ; "") }}

Once I did that in the text block, Slack finally posted again. But this bug never registered as an error unless you expanded the failed HTTP response nested three steps down in the execution log.

4. Using map and get elements in Slack messages from array inputs

This one took more trial and error than I’d like to admit. I had a set of tasks pulled in via Make’s “Search records” module from Airtable — each matching a specific tag — and I wanted one Slack message listing all of them. Easy, right? It’s just mapping over the array and joining text blocks. Except, I kept getting [object Object] in the Slack message body.

Eventually I realized that Make’s built-in map function expects you to extract keys manually. It doesn’t flatten anything. So you need something like:

{{ map(Tasks ; "concat('- ', get(1; "fields")['Name'])") }}

and then a join call immediately after that:

{{ join(map(Tasks ; "concat('- ', get(1; \"fields\")[\"Name\"]) "; "\n") }}

Once that showed up in Slack without [object Object], the entire thing clicked. But until then, I spent half an hour rechecking Slack formatting, thinking that’s where I messed up.

5. How Make’s scheduling sometimes queues 3 messages on one click

This one freaked people out in the team channel. I was using Make to trigger Slack from a webhook fired by a public form submission — hosted on a marketing tool that sent data via webhook after delay. What I didn’t realize: the webhook actually fires once per field group if someone returns to the form later and edits it during the delay window.

One submission turned into three webhooks. Each fired the same Make scenario, which ran fine, and sent three identical Slack alerts. My first instinct was to deduplicate using a record ID in Airtable — but these were coming from a tool that didn’t expose a unique ID per submission unless you signed up for advanced webhook access (which I didn’t even know existed until later).

The workaround? I had to add an internal deduplication layer in Make.

  • After receiving the webhook, generate an MD5 hash from all non-empty form values
  • Search Airtable for that hash — if it exists, stop
  • If not, create the record and send the Slack message
  • Store the hash in Airtable to stop future duplicates

I mean, it works. But this is one of those human-mechanics bugs — people edit form entries, so the system rethinks the submission.

6. When Slack formatting silently breaks due to non-breaking spaces

I copied a Markdown block from Notion into the “text” input for a Slack message and the formatting looked fine. Really clean. Until none of the bold or italic indicators worked in Slack. No error. Just plain text.

Turns out Notion (and sometimes Airtable) copy-paste adds Unicode non-breaking space characters where you wouldn’t expect them. In Slack, an asterisk between non-breaking spaces doesn’t count as bold. It renders like *not bold*.

I only caught it when I pasted the same block into a raw text editor and saw the weird spaces as encoded characters. At that point, I added a Text parser in Make that mirrored this transformation:

{{ replaceAll(OriginalText; char(160); ' ') }}

After that, Slack formatting was back. But that full Slack message had looked fine in preview — which makes this one of those invisible formatting bugs that cost half an hour before you even know you’re debugging formatting.

7. Real ways I now test Slack paths before rolling them out

I now do test runs for any Slack path using smokescreen messages, because I’ve been burned enough. A few tips that have actually saved time:

  • Use a dummy Slack channel that’s muted and shared with one coworker
  • Name your test messages with a unicode prefix (e.g., ⬛️ or 🔵) so they stand out
  • Add a timestamp explicitly — don’t rely on Slack’s built-in time label
  • Insert the scenario execution ID into the message footer — makes log correlation easier
  • Use message previews in Slack when possible — post via webhook once, then edit dynamically using later Make steps
  • Schedule post-delays of 5–10 seconds between Slack messages when testing loops
  • And yes, keep a Notion table where you list which message means what

Otherwise, you’ll hit that thing where someone asks “Why did the bot post that weird one-line table again?” and you’ll have no trace except “Ran successfully.”

8. That one condition you forgot to add that causes total chaos

This was the big one. I had a Slack alert on “task escalated” that fired downstream from a task status update. Except… I forgot to check if the escalation field was true. I literally left that out of the conditional filters.

So every task update — even spelling corrections — triggered the Slack alert. And nobody noticed for a day because the messages still looked legit. Everyone just assumed more escalations were happening.

Here’s the actual filter I should have used in Make:

AND(
  Status = "In Progress",
  Escalated = true
)

I’d only kept the Status check, assuming escalation was implied by transition. But even triaged tasks sometimes pass through “In Progress” before seeing real eyes.

Once I added the missing Escalated check, the chaos stopped. But that very first message — “Escalated: Add icon to login page” — will probably haunt our Slack forever.