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

  1. 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).
  2. Retry the test once after re-saving Telegram settings (save triggers a reload).
  3. 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

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


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/73c39554d7f0a572. Report an issue: GitHub.