The Bot Was Fine. My Test Payload Was Nonsense.
I spent an embarrassing amount of time blaming a Telegram webhook that was doing exactly what I told it to do. The payload I sent was {}. Valid JSON. Completely useless Telegram update.
me: it is valid JSON though
aiogram: lovely. where is update_id?
That was the whole bug, more or less. I was testing the endpoint as if “can FastAPI parse this body?” and “is this a real Telegram update?” were the same question. They are not. The first one passed. The second one quite reasonably fell over.
The annoying part was that the failure surfaced as a generic webhook error, which made the problem look deeper than it was. I checked routing, secrets, the dispatcher, and whether Telegram was doing something strange. Telegram was innocent. Rare occasion.
The fix was boring
I made the update boundary handle validation errors directly. A malformed body now returns a clean “not processed” result instead of turning into a 500 and pretending the server caught fire. Then I stopped using toy JSON and replayed payloads shaped like the updates Telegram actually sends.
This is such a small distinction, but it keeps showing up everywhere I build integrations. A request can be syntactically fine and still be nonsense. A model can return valid JSON and still violate the contract. A spreadsheet can have values and still have the wrong headers.
Anyway, the bot was fine. My test was bad. I would have preferred a more impressive ending too.