{"record":{"id":"9b019d0ebaf43554","repo":"MHSanaei/3x-ui","slug":"bot-not-started","errorCode":null,"errorMessage":"bot not started","messagePattern":"bot not started","errorType":"http","errorClass":null,"httpStatus":200,"severity":"warning","filePath":"internal/web/controller/setting.go","lineNumber":312,"sourceCode":"}\n\nfunc (a *SettingController) testTgBot(c *gin.Context) {\n\tenabled, err := a.settingService.GetTgbotEnabled()\n\tif err != nil || !enabled {\n\t\tjsonMsg(c, I18nWeb(c, \"pages.settings.tgBotNotEnabled\"), errors.New(\"telegram bot disabled\"))\n\t\treturn\n\t}\n\t// Import tgbot package would create a circular dependency, so we call\n\t// the test through the global function registered at startup.\n\tif testTgFunc != nil {\n\t\tif err := testTgFunc(); err != nil {\n\t\t\tjsonMsg(c, I18nWeb(c, \"pages.settings.tgTestFailed\")+\": \"+err.Error(), err)\n\t\t\treturn\n\t\t}\n\t\tjsonMsg(c, I18nWeb(c, \"pages.settings.tgTestSuccess\"), nil)\n\t\treturn\n\t}\n\tjsonMsg(c, I18nWeb(c, \"pages.settings.tgBotNotRunning\"), errors.New(\"bot not started\"))\n}\n\n// testTgFunc is set from web layer to test Telegram sending without circular imports.\nvar testTgFunc func() error\n\n// SetTestTgFunc registers the function used to test Telegram sending.\nfunc SetTestTgFunc(fn func() error) { testTgFunc = fn }\n\n// reloadTgbotFunc is wired from the web layer; importing tgbot here would be a circular dependency.\nvar reloadTgbotFunc func()\n\nfunc SetReloadTgbotFunc(fn func()) { reloadTgbotFunc = fn }\n\n// emailService is set from web layer.\nvar emailService *email.EmailService\n\n// SetEmailService registers the email service for test endpoints.\nfunc SetEmailService(s *email.EmailService) { emailService = s }","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/controller/setting.go#L294-L330","documentation":"testTgBot delegates the actual send through testTgFunc, a function variable registered at startup by the web layer to avoid a circular import with the tgbot package. If the variable is still nil the handler returns 'bot not started' — meaning the Telegram bot runtime was never wired up in this process (typically the bot is disabled or failed to start, so nothing called SetTestTgFunc).","triggerScenarios":"Bot enabled in settings but startup wiring never ran (init error swallowed); calling the endpoint in a process/CLI mode that skips web-server boot; a race where the test fires before startup registration.","commonSituations":"Immediately after enabling the bot but before a restart; custom builds that strip the tgbot registration; startup partial failure.","solutions":["Restart the panel so the web layer registers the bot and SetTestTgFunc runs","Verify the tgbot package actually initialized (look for its startup log lines)","If custom wiring was removed, restore the SetTestTgFunc call in the web bootstrap"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restart the panel after enabling the bot so SetTestTgFunc is registered","Check startup logs for the tgbot wiring line before invoking the test endpoint"],"tags":["telegram","initialization","settings","bot"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}