Skip to content

fix(relay): unbounded recursion in sendTelegram on 429 rate limit #3060

@SebastienMelki

Description

@SebastienMelki

Bug

In scripts/notification-relay.cjs:304-308, sendTelegram calls itself on HTTP 429 with no retry counter:

if (res.status === 429) {
  const body = await res.json().catch(() => ({}));
  const wait = ((body.parameters?.retry_after ?? 5) + 1) * 1000;
  await new Promise(r => setTimeout(r, wait));
  return sendTelegram(userId, chatId, text); // "single retry" — but no guard
}

The comment says "single retry" but there's no depth/counter parameter to enforce it. If Telegram keeps returning 429 (sustained rate limiting during alert bursts), this recurses indefinitely.

Impact

Under sustained Telegram rate limiting, the relay could hit a stack overflow and crash on Railway. In practice this is rare since retry_after usually resolves it, but it's not guaranteed.

Fix

Add a _retryCount parameter (default 0), pass _retryCount + 1 on recursion, bail if _retryCount >= 1.

Verification Steps

  • Read sendTelegram signature — confirm it has a _retryCount parameter defaulting to 0
  • Confirm the recursive call passes _retryCount + 1
  • Confirm a guard bails (returns false + logs) when _retryCount >= 1
  • Confirm non-429 paths are unaffected (no behavioral change for 200, 400, 403, 401)

Ref: #2173

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions