DEV Community

Cover image for My mailer printed "campaign sent". It had sent to nobody.
Manpreet Singh
Manpreet Singh

Posted on Originally published at singhlabs.dev AI-assisted

My mailer printed "campaign sent". It had sent to nobody.

I make small tools that catch AI agents reporting success while quietly doing nothing. That is the entire product line. One of them is literally called trust issues.

Last week I shipped a mailer that printed campaign sent to list twice, five days apart, having delivered to zero people.

How it looked from the inside

I have a small list — 47 people who followed my writing elsewhere and agreed to hear from me here. I wrote them an email. The workflow ran. It said this:

campaign 2 sent to list ***
Enter fullscreen mode Exit fullscreen mode

Green tick. Job done. Four days later I sent a second one. Same message, same green tick.

Then nobody replied to either. Not one person. I spent an evening concluding that my writing was bad, that the list was dead, that three weeks of work had landed on nobody who cared.

Eventually I did the obvious thing and looked at the numbers instead of my feelings.

LISTS
      0 subscribers  Your first list

CAMPAIGNS (newest first)

  "I measured where my AI coding tokens actually go. 0.2%."
    status sent   sent 2026-08-07T09:24:06+05:30
    delivered 0 of 0   opens 0   clicks 0

  "Moving my writing home — and what I've been building"
    status sent   sent 2026-08-03T19:40:50+05:30
    delivered 0 of 0   opens 0   clicks 0
Enter fullscreen mode Exit fullscreen mode

Zero subscribers. Meanwhile 48 contacts sat in the account, imported correctly, never attached to the list the campaigns were addressed to. Both emails went out to an empty room.

Nobody ignored my emails. Nobody received them. Five days of silence I had taken personally was a config error.

The bug is not the interesting part

Contacts not attached to a list is a boring mistake. Ten minutes to fix.

The interesting part is that my code told me it had worked. It called the create-campaign endpoint. It called send. Both returned 200. So it printed success — because from the code's point of view, everything it did had succeeded.

It had verified the call. It had verified nothing about the effect.

That distinction is the whole of my product line, written on my own site, and I still shipped past it. An agent that says "I fixed the tests" has usually verified that it edited a file, not that anything passes. A deploy script that says "deployed" has usually verified that the API accepted the request. The gap between the call returned 200 and the thing you wanted actually happened is where this class of bug lives, and it is enormous.

Then a second bug nearly hid the fix

I attached the contacts, re-sent, and went to confirm. It still said zero.

For twenty minutes I believed the repair had failed. It hadn't. My stats script was reading the wrong endpoint, and the two endpoints disagree:

singular   /contacts/lists/2   → {"name":"Your first list","total":47}
collection /contacts/lists     → [{"name":"Your first list","total":0}]
Enter fullscreen mode Exit fullscreen mode

Same list. Same second. Two different answers from the same provider. The collection endpoint reports 0 for a list that demonstrably has 47 members, and my code happened to read that one.

So I had a broken thing, then a broken measurement of the thing, and the measurement was what I was using to decide whether the fix had worked. When two sources disagree, find out which one lies before you conclude anything. I nearly re-fixed a bug that was already fixed.

How I actually confirmed it, in the end

Not from a dashboard. From the account's send credits.

The free plan allows 300 sends a day. Before the run: 300. After: 253. Exactly 47 gone — one per subscriber. That is the only number in this whole story that could not be produced by a bug in my own reporting, because it came from the provider's billing rather than from anything I wrote.

Then the email arrived in my own inbox, which is the other kind of proof that doesn't lie.

What I changed

  • The sender now refuses to send to an empty list. It checks the subscriber count first and exits with an error. A delivery of zero is a failure, and it must look like one.

  • The stats script resolves each list individually, with a comment naming the endpoint that lies, so nobody re-learns this.

  • Success messages now carry a number. sent to 47 subscribers, never campaign sent. A message with a count in it cannot be true and empty at the same time.

That last one is the cheap habit worth stealing. Most misleading log lines are misleading because they describe an action rather than a result. "Backup complete" versus "backed up 1,204 files, 3.1 GB". One of those can be printed by a script that copied nothing.


The uncomfortable version of this story is that I sell the fix. I write tools that hold an agent's claim against what actually changed on disk, because a confident summary is not evidence. Then I wrote a summary of my own, believed it, and lost five days and most of an evening to it.

Knowing the failure mode is not the same as being immune to it. If anything, I was slower to check because the message came from code I had written myself.

Everything quoted here is real output from my own account, lightly trimmed for width. The list is 47 people; if you are one of them, that is why the first email arrived twice.

Read next: I researched loop engineering to build a product. I built nothing. · The models are a point apart. The harnesses are on fire.


Originally published at singhlabs.dev.

Top comments (0)