A customer called on a Wednesday afternoon to follow up on a form inquiry they had submitted almost two weeks earlier. They were not angry, just checking in. Two weeks felt like a long time to wait.
It was. But not for the reason they thought.
The Dashboard Said Everything Was Fine
My first move was to search Help Scout for a ticket tied to their email address. Nothing came up. I tried their name. Still nothing. My working theory at that point was that the form itself had malfunctioned and the submission had never actually gone through.
Then I looked at the Zap.
The integration responsible for pulling inquiry form submissions into Help Scout had been running reliably for four months. I had set it up, tested it thoroughly, and monitored it through a full week of real traffic before trusting it with unattended operation. It showed as active. No failed tasks in the recent history. No error notifications in my inbox. The task history showed nothing at all for the past twelve days, not failed runs, just no runs. An absence where there should have been activity.
The webhook endpoint was technically alive. I could confirm that from the form vendor's dashboard: forty-three submissions in the last twelve days, each one returning a 200 OK from Zapier's endpoint. Received, acknowledged, and apparently gone.
Forty-three people had asked for help. Zero tickets had been created.
One Field Name
I started tracing the Zap logic step by step.
The webhook received the payload. A mapping step extracted specific fields from the JSON: name, email address, message, inquiry type. Then a filter: if the email field came back empty, stop the task. This guard had been added months earlier to prevent bot submissions from creating noise in the inbox. Nothing unusual. I had written that filter myself and trusted it.
The form vendor had pushed a minor update three weeks before. I had seen the changelog notification when it arrived. Mostly visual changes and a performance improvement. Buried near the bottom: field naming standardization. They had cleaned up their API response schema, renaming customer_email to email. For backward compatibility, the old key was still present in every response payload, but it now returned an empty string.
The Zap was still referencing customer_email. Empty string. The filter evaluated correctly, found no email address, and stopped processing. Every single time.
No error, because nothing had broken. The filter was doing exactly what it had been asked to do. It was asking about the wrong field. The difference is invisible to any monitor that only watches for failure states.
Fixing the field name took about four minutes.
The Long Part
The manual recovery took the rest of the day.
I pulled every submission from the form vendor's export: timestamps, names, email addresses, the questions and requests people had typed out. Forty-three records. I went through them individually, cross-referencing each one against Help Scout to check whether the person had eventually reached out through a different channel after hearing nothing back from the form. Some had, and those situations had been handled eventually, though later than they should have been. Others had not. Fourteen people had written in and were still waiting.
I wrote individual replies to each one. Not a bulk email, not a template with the name swapped in, but actual responses to the specific question or request in each submission. For a few that involved more complex situations, I flagged internally so someone could follow up with a direct call the same afternoon.
None of those emails mentioned a webhook or a field name. The customer who had called that morning got her answer and continued working with the company. The explanation she received was simply that her inquiry had been delayed and was being handled now.
The afternoon became the evening.
The Wrong Kind of Monitoring
After finishing, I wrote a short incident note documenting what had happened, the root cause, and what I was changing. One line in that note kept standing out: "Zero errors. Zero tickets. Both true at the same time."
That sentence describes the actual gap. Not the field name, which was a minor vendor change and a straightforward fix. The gap was that the monitoring infrastructure was watching for failure, and this was not a failure by any technical definition. It was an absence. The Zap was healthy. The filter was healthy. The webhook endpoint was healthy. The only thing that was not healthy was the outcome, and no part of the monitoring was configured to notice that.
Error alerts watch for things breaking loudly: a failed task, a 4xx or 5xx response, an exception. They do not watch for things stopping quietly. A filter that evaluates correctly on malformed data does not break. It just does nothing, and to a system that only checks for errors, nothing happening looks exactly like everything working perfectly.
Three additions went in over the following hour.
First, a scheduled Zap that runs once per day and counts the tickets created in Help Scout in the previous 24 hours, posting the number to a Slack channel. On a normal weekday, the expected range is between eight and fifteen. A zero on a Tuesday is not a quiet day; it is investigate immediately.
Second, an error path on the filter step itself. Previously, a failed filter condition terminated the task silently. Now it writes the raw JSON payload to a Google Sheet with a timestamp. That sheet gets reviewed every week. Most weeks it is empty. When it is not, there is something to look at.
Third, a line in the team's monthly operations review: open the form vendor's changelog and scan for field renames, schema changes, or new required parameters. Two minutes of reading. It has caught one other relevant change in the time since.
The daily count notification has been running for eight months. It has flagged two real problems before anyone had to call.
What Breaks Without Breaking
Most integrations get built with error monitoring and stop there. If the Zap fails, send a notification. If the HTTP response is a 500, write a log entry. This covers the loud failures well, and the loud failures are the ones most people think about when building a new automation.
But integrations also fail quietly. A filter that was correct when written and is still correct now, but evaluates on upstream data that has drifted. A mapping step referencing a key that was renamed in a vendor update. A condition designed to handle one edge case that inadvertently catches real traffic after a schema change. These produce no error. They produce silence.
Silence looks identical to success on any dashboard that only watches for failure.
Any automation that processes expected, recurring volume needs two monitors: one for errors, and one for the absence of expected activity. The second monitor is simpler to build than it sounds. It is often just a daily count and a threshold. It is also the one most people skip, because zero errors feels like green, and green feels like done.
The customer who called that Wednesday was patient. She got her answer. I never mentioned the forty-three submissions that had been silently discarded while the dashboard stayed clean and green.
Building the count notification was cheaper than that afternoon. It is the kind of fix that pays for itself once and then keeps running. If your automations process regular volume and you are only watching for errors, this is worth an hour of your time. Not because the failure I described is common, but because the class of failure it represents is.
One More Thing to Build
If you run any webhook-based automation that should process a relatively predictable volume of events, the simplest possible safeguard is a count check: how many records did this automation create yesterday? Set a threshold. Alert if it drops below. Route the alert somewhere visible.
The specific implementation does not matter much. A scheduled Zap, a Power Automate flow checking a SharePoint list count, an n8n workflow querying a database row count, all of these work. What matters is that someone or something notices when activity stops, not just when something breaks.
Questions about setting this up for your own stack? Drop me a line and I am happy to look at the specific setup with you.
Comments