{"record":{"id":"881412428dfb604a","repo":"Hmbown/CodeWhale","slug":"telegram-getupdates-conflict-another-bridge-is-polling-this","errorCode":null,"errorMessage":"Telegram getUpdates conflict; another bridge is polling this bot token. Stop the other bridge process or use a different token.","messagePattern":"Telegram getUpdates conflict; another bridge is polling this bot token\\. Stop the other bridge process or use a different token\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integrations/telegram-bridge/src/index.mjs","lineNumber":147,"sourceCode":"        timeout: config.pollTimeoutSeconds,\n        allowed_updates: [\"message\", \"callback_query\"]\n      });\n      pollingConflictAttempts = 0;\n      for (const update of updates || []) {\n        try {\n          await handleIncomingUpdate(update);\n          await markUpdateHandled(update);\n        } catch (error) {\n          console.error(\"failed to handle incoming Telegram update\", error);\n          break;\n        }\n      }\n    } catch (error) {\n      if (looksLikePollingConflict(error)) {\n        const waitMs = telegramPollingConflictDelayMs(pollingConflictAttempts);\n        pollingConflictAttempts += 1;\n        if (waitMs == null) {\n          throw new Error(\n            \"Telegram getUpdates conflict; another bridge is polling this bot token. Stop the other bridge process or use a different token.\"\n          );\n        }\n        console.warn(\n          `Telegram getUpdates conflict; another bridge is polling this bot. Retrying in ${Math.round(waitMs / 1000)}s.`\n        );\n        await delay(waitMs);\n        continue;\n      }\n      pollingConflictAttempts = 0;\n      const waitMs = telegramRetryDelayMs(error);\n      console.error(`Telegram poll failed: ${error.message}. Retrying in ${Math.round(waitMs / 1000)}s.`);\n      await delay(waitMs);\n    }\n  }\n}\n\nasync function markUpdateHandled(update) {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/integrations/telegram-bridge/src/index.mjs#L129-L165","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (two terminals, same token)\nBRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs  # terminal 1\nBRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs  # terminal 2 -> conflict\n\n// after\nBRIDGE_TELEGRAM_BOT_TOKEN=A... node src/index.mjs  # terminal 1\nBRIDGE_TELEGRAM_BOT_TOKEN=B... node src/index.mjs  # terminal 2, distinct bot","handlingStrategy":"retry","validationCode":"// Before starting, verify no other consumer: if a webhook is set, getUpdates will conflict.\nconst me = await fetch(`https://api.telegram.org/bot${token}/getWebhookInfo`).then((r) => r.json());\nif (me.result?.url) {\n  await fetch(`https://api.telegram.org/bot${token}/deleteWebhook`, { method: \"POST\" });\n}","typeGuard":null,"tryCatchPattern":"try {\n  await pollTelegram();\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"getUpdates conflict\")) {\n    console.error(\"Another process is polling this bot token. Stop it or use a different token.\");\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["telegram","polling-conflict","network","concurrency"],"backgroundTag":"address-already-in-use","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}