Problem
When a message dispatch fails (provider error, rate limit, empty response), Telegram now sends the user a meaningful fallback message. All other channels silently drop the failure — the user receives nothing and has no way to know something went wrong.
Current behavior per channel
| Channel |
On dispatch error |
| Telegram |
Sends user a typed fallback message (rate limit / empty response / general) ✅ |
| LINE |
Sends a hardcoded "Sorry, I encountered an error..." string (no error routing) ⚠️ |
| Discord |
Logs only — user sees nothing ❌ |
| Slack |
Logs only — user sees nothing ❌ |
| Signal |
Logs only — user sees nothing ❌ |
| WhatsApp (web) |
Logs only — user sees nothing ❌ |
Proposed fix
Add the same fallback pattern to each channel's dispatch site:
- Track
lastError via onError callback and outer try/catch
- Check delivery state after dispatch (nothing delivered + failure/skip)
- Send a user-visible message using
resolveFailoverReasonFromError + EmptyResponseError routing (same logic as Telegram)
Extract the error-message-selection logic into a shared helper (e.g. src/auto-reply/reply/delivery-fallback.ts) so it isn't duplicated across channel files.
Related
- Introduced in the model-fallback empty-response fix PR (see
EmptyResponseError in src/agents/model-fallback.ts)
resolveFailoverReasonFromError already handles rate-limit / auth / timeout classification
Problem
When a message dispatch fails (provider error, rate limit, empty response), Telegram now sends the user a meaningful fallback message. All other channels silently drop the failure — the user receives nothing and has no way to know something went wrong.
Current behavior per channel
"Sorry, I encountered an error..."string (no error routing)Proposed fix
Add the same fallback pattern to each channel's dispatch site:
lastErrorviaonErrorcallback and outer try/catchresolveFailoverReasonFromError+EmptyResponseErrorrouting (same logic as Telegram)Extract the error-message-selection logic into a shared helper (e.g.
src/auto-reply/reply/delivery-fallback.ts) so it isn't duplicated across channel files.Related
EmptyResponseErrorinsrc/agents/model-fallback.ts)resolveFailoverReasonFromErroralready handles rate-limit / auth / timeout classification