Detection is well covered on this forum. Error Workflow for hard failures, an inline validation step into Stop and Error for the green-but-empty ones, a heartbeat for runs that never fired. I’ve read those threads and built all three.
What I couldn’t find was the layer after detection. The alert tells you something broke. It doesn’t tell you what to do about it.
An expired Google OAuth credential, a client renaming a column in their sheet, and a bug in my own expression all arrive looking identical — “workflow failed.” Two of those are a message to the client. One is me opening my laptop.
Someone in another thread here put the cost better than I had: the client doesn’t experience three weeks of silent failure as three weeks. They experience the thirty seconds where they ask what happened and you don’t have an answer. “Your OAuth token expired on the 4th, here’s the trail” and “I’m not sure yet” are the same technical situation and completely different conversations.
So I built a layer that tries to answer that question and puts the verdict in the alert itself. It pulls executions from the n8n API, walks runData per node, sorts each failure into credential expired / client data changed / third-party API issue / workflow bug / unclear, and sends a batched email where the subject line is the verdict — “3 new failures — 2 yours, 1 not yours.” It also does a read-only scan of your existing execution history when you first connect, which mostly exists because I wanted to know what my own history actually contained. It was not what I assumed.
60-second demo, no audio: [ https://youtu.be/tj_pfne3Ndc\]
The design decision I’d like feedback on
Classification is deliberately conservative. It returns “unclear” rather than guessing, because a confidently wrong blame label is worse than no label at all — tell someone “not your bug” when it is their bug and the whole thing stops being trustworthy.
Two things I got wrong on the way there:
- invalid_grant and a 401 are reliable signals for a dead credential. But a broken Google OAuth credential often surfaces as “Unable to sign without access token” with no HTTP code at all, because the request was never sent. My first version keyed on status codes and missed that class entirely. It sat in “unclear” for a while before I worked out why nothing matched it.
- Matching on the word “token” alone is a trap. OpenAI’s context-length errors are full of it and have nothing to do with auth.
Which points at the real problem: every integration fails in its own shape, and text matching only gets you so far.
Where I actually am
I don’t run an agency. I built this because the triage problem kept bothering me, and the client names in the demo are my own test data — nobody is using it yet. Which is why I’m posting here rather than anywhere else.
Two questions I can’t answer from my own data:
Does the unclassified bucket shrink as you cover more integrations, or stay roughly constant because every new client brings a new node type with its own error shape? I’ve been assuming the long tail converges. If it doesn’t, this is maintenance forever.
And more importantly — is ownership even the right axis? Once an alert reaches you, is working out whose fault it is fast enough that automating it isn’t worth much? I’d rather hear that now than after building another layer on top of it.