Hmbown/CodeWhale · error
Telegram getUpdates conflict; another bridge is polling…
Error message
Telegram getUpdates conflict; another bridge is polling this bot token. Stop the other bridge process or use a different token.
What it means
Telegram's Bot API allows only one getUpdates (long-poll) consumer per bot token. When the bridge detects a 409 polling conflict, it retries with backoff a limited number of times (pollingConflictAttempts); once the delay budget is exhausted it throws this terminal error. It means another process — often a duplicate bridge or a webhook-configured bot — is competing for the same token.
Solutions
- Find and stop the other process polling the same token (ps aux | grep telegram-bridge, check other hosts/containers).
- Use a different bot token (create a new bot via @BotFather) for one of the instances.
- If a webhook is set, delete it: call deleteWebhook for the token, since webhooks conflict with getUpdates.
- Restart only one bridge instance after confirming no duplicate is running.
Example fix
// before (two terminals, same token) BRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs # terminal 1 BRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs # terminal 2 -> conflict // after BRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs # terminal 1 BRIDGE_TELEGRAM_BOT_TOKEN=B... node src/index.mjs # terminal 2, distinct bot
Defensive patterns
Strategy: retry
Validate before calling
// Before starting, verify no other consumer: if a webhook is set, getUpdates will conflict.
const me = await fetch(`https://api.telegram.org/bot${token}/getWebhookInfo`).then((r) => r.json());
if (me.result?.url) {
await fetch(`https://api.telegram.org/bot${token}/deleteWebhook`, { method: "POST" });
} Try / catch
try {
await pollTelegram();
} catch (err) {
if (err instanceof Error && err.message.includes("getUpdates conflict")) {
console.error("Another process is polling this bot token. Stop it or use a different token.");
process.exit(1);
}
throw err;
} Prevention
- Run exactly one bridge instance per bot token; use a lockfile/pidfile or supervisor single-instance policy.
- Give each environment (dev/staging/prod) its own bot token from @BotFather.
- Delete webhooks on tokens you intend to long-poll.
- Monitor for repeated conflict warnings — they are the early signal of a duplicate consumer.
When it happens
Trigger: pollTelegram's fetch fails with a polling-conflict error (looksLikePollingConflict true) on every retry until telegramPollingConflictDelayMs returns null, i.e. a second process has been calling getUpdates with the same bot token for the whole backoff window.
Common situations: Two bridge instances running locally or on different hosts with the same TELEGRAM_BOT_TOKEN, an old process that never died, a dev instance and a production instance sharing a token, or a webhook left enabled on the bot.
Related errors
- A saved trace identifier collided. Try saving again.
- a window change is already in progress
- another Codewhale process
- Another pet recorder is using this output.
- building bundle fetch client failed
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/881412428dfb604a.
Report an issue: GitHub.
Appendix: source
Thrown at integrations/telegram-bridge/src/index.mjs:147
timeout: config.pollTimeoutSeconds,
allowed_updates: ["message", "callback_query"]
});
pollingConflictAttempts = 0;
for (const update of updates || []) {
try {
await handleIncomingUpdate(update);
await markUpdateHandled(update);
} catch (error) {
console.error("failed to handle incoming Telegram update", error);
break;
}
}
} catch (error) {
if (looksLikePollingConflict(error)) {
const waitMs = telegramPollingConflictDelayMs(pollingConflictAttempts);
pollingConflictAttempts += 1;
if (waitMs == null) {
throw new Error(
"Telegram getUpdates conflict; another bridge is polling this bot token. Stop the other bridge process or use a different token."
);
}
console.warn(
`Telegram getUpdates conflict; another bridge is polling this bot. Retrying in ${Math.round(waitMs / 1000)}s.`
);
await delay(waitMs);
continue;
}
pollingConflictAttempts = 0;
const waitMs = telegramRetryDelayMs(error);
console.error(`Telegram poll failed: ${error.message}. Retrying in ${Math.round(waitMs / 1000)}s.`);
await delay(waitMs);
}
}
}
async function markUpdateHandled(update) {View on GitHub (pinned to 433685b202)