{"record":{"id":"d6c290e58be81805","repo":"HKUDS/Vibe-Trading","slug":"webhook-secret-token-is-required-when-telegram-mod","errorCode":null,"errorMessage":"webhook_secret_token is required when Telegram mode is webhook","messagePattern":"webhook_secret_token is required when Telegram mode is webhook","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"agent/src/channels/telegram.py","lineNumber":415,"sourceCode":"        value = value.strip() or \"/telegram\"\n        if not value.startswith(\"/\"):\n            raise ValueError('webhook_path must start with \"/\"')\n        return value\n\n    @model_validator(mode=\"after\")\n    def validate_webhook_config(self) -> \"TelegramConfig\":\n        if self.mode != \"webhook\":\n            return self\n\n        url = self.webhook_url.strip()\n        if not url:\n            raise ValueError(\"webhook_url is required when Telegram mode is webhook\")\n        parsed = urlparse(url)\n        if parsed.scheme != \"https\" or not parsed.netloc:\n            raise ValueError(\"webhook_url must be a public HTTPS URL\")\n        secret = self.webhook_secret_token.strip()\n        if not secret:\n            raise ValueError(\"webhook_secret_token is required when Telegram mode is webhook\")\n        if len(secret) > 256 or re.match(r\"^[A-Za-z0-9_-]+$\", secret) is None:\n            raise ValueError(\n                \"webhook_secret_token must be 1-256 characters using only A-Z, a-z, 0-9, _ and -\"\n            )\n        return self\n\n\nclass TelegramChannel(BaseChannel):\n    \"\"\"\n    Telegram channel using long polling or webhook mode.\n\n    Long polling is the default. Webhook mode requires a public HTTPS URL and a\n    Telegram secret token.\n    \"\"\"\n\n    name = \"telegram\"\n    display_name = \"Telegram\"\n","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/telegram.py#L397-L433","documentation":"Raised by TelegramChannel config validation when mode is webhook but webhook_secret_token is empty or whitespace-only. The secret token is used with Telegram's setWebhook secret_token so the bot can verify update requests actually came from Telegram. Without it, anyone who discovers the webhook URL could post forged updates, so the library refuses to start.","triggerScenarios":"Constructing the Telegram channel config with mode=\"webhook\" (or TELEGRAAM/webhook env config) while webhook_secret_token is unset, empty, or only spaces. The model validator strips the value and raises when the result is falsy.","commonSituations":"Copying a polling-mode config to webhook mode and forgetting the secret; providing the secret via an env var name that isn't set (expands to empty string); secrets loaded from a .env file that isn't loaded in the deploy environment.","solutions":["Set webhook_secret_token to a random token, e.g. generate with openssl rand -hex 32 (matches [A-Za-z0-9_-])","Verify the env var actually resolves in the runtime environment (print it or use the same loader the app uses)","If you truly want polling instead of webhooks, set mode to polling rather than leaving webhook without a secret"],"exampleFix":"# before\nTelegramConfig(mode=\"webhook\", webhook_url=\"https://bot.example.com/tg/hook\")\n# after\nimport secrets\nTelegramConfig(\n    mode=\"webhook\",\n    webhook_url=\"https://bot.example.com/tg/hook\",\n    webhook_secret_token=secrets.token_urlsafe(32),\n)","handlingStrategy":"validation","validationCode":"import secrets\nfrom agent.src.channels.telegram import TelegramConfig  # adjust import\n\ndef make_tg_config(**kw) -> TelegramConfig:\n    if kw.get(\"mode\") == \"webhook\" and not (kw.get(\"webhook_secret_token\") or \"\").strip():\n        kw[\"webhook_secret_token\"] = secrets.token_hex(32)  # auto-provision\n    return TelegramConfig(**kw)","typeGuard":"def has_webhook_secret(cfg: dict) -> bool:\n    return cfg.get(\"mode\") != \"webhook\" or bool(str(cfg.get(\"webhook_secret_token\", \"\")).strip())","tryCatchPattern":null,"preventionTips":["Generate webhook secrets at deploy time with secrets.token_hex(32)","Fail fast in CI by constructing the config object before starting the app","Use a secrets manager that errors on missing keys rather than returning empty strings"],"tags":["telegram","webhook","config-validation","security"],"backgroundTag":"webhook-secret-missing","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}