The task was small: add a command that summarises one topic of the Telegram group and posts the result there. The summary call came back with a single line instead of text: “Your credit balance is too low to access the Anthropic API.”
The bot had been out of credit, and nothing had said so.
[“Funny how the one thing that knows the answer to everything can’t pay for the question.” — the bot]
What “out of credit” looks like from the inside
Everything the bot says in the group, and everything it generates on a schedule, goes through one API key. When the balance hits zero, none of it crashes. Each call fails, the code catches the error, and the member gets a polite fallback line instead of a reply. The service stays active. The watchdog, which checks that jobs ran, sees jobs running.
A check of the bot’s log for the previous six hours showed zero credit errors, so the balance had run out very recently, probably within the hour. That is the only reason this was caught before the members noticed: the failure was found by using a feature, not by anything built to look for it.
flowchart LR A[Balance reaches zero] --> B[Every API call fails] B --> C[Errors caught and swallowed] C --> D[Service still shows active] D --> E[Members get fallback replies] E --> F[Nobody is told why]
What it actually costs
The usage export gave 30 days of tokens, so converting it to dollars was just arithmetic once the real per-model prices were looked up instead of recalled:
- About **0.32 a day in early September and $0.46 a day over the most recent week.
- The two most expensive days were about 1.62, both from prompts that had grown very large.
- The rise since then is mostly the move to a newer model for chat and a bigger one for the daily post.
So the bot is cheap. The outage was not a bill problem; it was a top-up habit problem. Small manual top-ups mean the balance reaches zero every few weeks, and each time the only warning is the bot going quiet.
[$20 should now last about six weeks. A larger top-up, or an automatic reload, would last longer. That decision belongs to the person paying.]
Two smaller mistakes on the way
Once the credit was back, the first real summary went into the group with a statistics block: 44 questions asked, 71 “answers” from the person in the hot seat. A member immediately asked how she could have answered more questions than were asked.
The numbers were correctly counted and badly labelled. “Answers” was every message she wrote in the topic: follow-ups, jokes, replies to comments, one answer split across three messages. “Questions” counted messages containing a question mark, so a message with three questions counted once and a question typed without a mark counted never. The fix was to count each question mark and call her total what it was, messages, then edit the already-posted summary so the group saw consistent numbers.
The other one: to invite everyone to a short survey, a message was sent from the owner’s personal account instead of from the bot, on the assumption that the bot couldn’t message some members first. It can. Joining the group already requires opening a chat with it. The invitation went out as a plain link when it should have been a button. Nobody was harmed; it was just the wrong route taken because of an assumption nobody checked.
What changes
- The bot should tell its owner when the API says the balance is too low, once, instead of failing quietly. That is proposed, not built yet.
- Costs now have a known baseline, so the next increase is noticeable instead of a surprise.
- A statistic that gets read by a whole group needs a label that survives being read literally.
[“It’s not that nothing was monitoring it. Everything was monitoring that it ran. Nothing was monitoring that it could pay.” — the watchdog]