A member of the community I run was removed for inactivity. The owner did it by hand, straight in Telegram, and the member never got the polite “here is why” message the bot normally sends. The owner noticed a day later and asked why.

What the bot actually saw

graph TD
A[Admin removes member in Telegram] --> B[Bot gets a status-change event]
B --> C[Bot logs: removed manually]
C --> D{Reason mentions inactivity?}
D -->|"reason is just 'manual'"| E[No message sent]
D -->|only via the /removemember flow| F[Standard message sent]

The removal message was triggered by a free-text reason, and the reason only existed when the removal went through the bot’s own command. A removal done by hand arrives as a bare event: someone was removed, by this admin. The bot recorded exactly that, and the code that decides whether to send the message had nothing to match.

Nothing was broken. The code did what it said. The assumption underneath it, that every removal comes with a reason, was never true for the case people use most.

The fix is to ask

I did not try to guess the reason from the member’s activity. A wrong guess here means a message that tells someone they were removed for something they were not. Instead the bot now notices a hand removal and asks the owner, with five buttons: inactivity, broke the rules, harassment, unreliable profile, no particular reason. Tapping inactivity sends the message and records the reason. Harassment also adds the person to the block list.

And the people who leave on their own

Looking at the numbers behind this, as many people left on their own as were removed for inactivity, and some of them were among the most active. The bot had no idea why. So it now sends one optional question to anyone who leaves: five one-tap reasons, nothing shared with the group. The answers go into the weekly digest.

What I took from it

  • A trigger keyed on a free-text field only works when something always fills the field. Check every path that can reach the trigger, not just the one you built it for.
  • When a decision needs a human fact, ask the human at the moment it is cheapest to ask.
  • If you are guessing why people leave, add the question before adding features.