MHSanaei/3x-ui · error
telegram API test failed: %w
Error message
telegram API test failed: %w
What it means
Wrapper produced inside the same SetTestTgFunc closure when TestConnection() fails while the bot IS running. The %w chain carries the underlying cause: almost always 'bot not initialized' (handle lost, e.g. bot stopped between the IsRunning check and the call) or 'API unreachable: ...' (network/401 to api.telegram.org).
Source
Thrown at internal/web/web.go:626
})
}
}
// Register email subscriber (always — it checks smtpEnable at runtime)
emailService := email.NewEmailService(s.settingService)
emailSub := email.NewSubscriber(s.settingService, emailService)
s.bus.Subscribe("email-notifier", emailSub.HandleEvent)
// Wire email service to controller for test endpoint
controller.SetEmailService(emailService)
// Wire Telegram test function to controller
controller.SetTestTgFunc(func() error {
if !s.tgbotService.IsRunning() {
return fmt.Errorf("telegram bot is not running (check token and chat ID)")
}
if err := s.tgbotService.TestConnection(); err != nil {
return fmt.Errorf("telegram API test failed: %w", err)
}
s.tgbotService.SendMsgToTgbotAdmins("✅ Test message from 3x-ui")
return nil
})
controller.SetReloadTgbotFunc(func() {
enabled, err := s.settingService.GetTgbotEnabled()
if err != nil || !enabled {
if s.tgbotService.IsRunning() {
s.tgbotService.Stop()
}
if s.bus != nil {
s.bus.Unsubscribe("tg-notifier")
}
return
}
// Start() stops any previous receiver first, so it is safe whether or not the bot is already running.
tgBot := s.tgbotService.NewTgbot()View on GitHub (pinned to ad32144c42)
Solutions
- Read the tail of the wrapped error to pick the real cause, then apply the fix for that leaf error (401 -> re-paste token; network -> fix egress; 'not initialized' -> reload bot).
- Retry the test once after re-saving Telegram settings (save triggers a reload).
- If it recurs on every save, check that the tgbot reload path (SetReloadTgbotFunc) is completing without error in the logs.
Example fix
// before
if err := s.tgbotService.TestConnection(); err != nil {
return fmt.Errorf("telegram API test failed: %w", err)
}
// after — surface the leaf cause directly since the wrapper adds no information
if err := s.tgbotService.TestConnection(); err != nil {
return fmt.Errorf("telegram test failed: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
if err := testTg(); err != nil {
unwrapped := errors.Unwrap(err) // skip the 'telegram API test failed' layer
if unwrapped != nil && strings.Contains(unwrapped.Error(), "bot not initialized") {
// reload bot; else fix network/token per leaf error
}
} Prevention
- Unwrap %w chains before choosing a remedy — this wrapper's message adds no cause.
- Avoid concurrent reload+test; serialize via the settings mutex.
When it happens
Trigger: Race where the bot is stopped/reloaded between the IsRunning() check and TestConnection(); or a running-but-broken bot state (token was valid at start, revoked since; server lost egress to Telegram).
Common situations: Revoked/regenerated tokens while the bot was live; intermittent egress to api.telegram.org; concurrent settings save reloading the bot during a test.
Related errors
- API unreachable: %w
- telegram bot disabled
- bot not started
- ❌ Failed to get inbounds.
- tg_id must be a positive integer
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/73c39554d7f0a572.
Report an issue: GitHub.