MHSanaei/3x-ui · error
API unreachable: %w
Error message
API unreachable: %w
What it means
Returned by Tgbot.TestConnection when b.GetMe() fails, i.e. the bot handle exists but the HTTPS call to api.telegram.org failed. Causes are network-level (DNS, firewall, no route to Telegram from the server's location) or API-level (401 unauthorized for an invalid/revoked token; the %w chain preserves the underlying error).
Source
Thrown at internal/web/service/tgbot/tgbot_send.go:271
}
if err := bot.DeleteMessage(context.Background(), ¶ms); err != nil {
logger.Warning("Failed to delete message:", err)
} else {
logger.Info("Message deleted successfully")
}
}
// TestConnection verifies the bot token is valid and the API is reachable.
func (t *Tgbot) TestConnection() error {
tgBotMutex.Lock()
b := bot
tgBotMutex.Unlock()
if b == nil {
return fmt.Errorf("bot not initialized")
}
me, err := b.GetMe(context.Background())
if err != nil {
return fmt.Errorf("API unreachable: %w", err)
}
_ = me
return nil
}
View on GitHub (pinned to ad32144c42)
Solutions
- Check the wrapped error text: '401 Unauthorized' means the token is wrong/revoked — paste the current token from BotFather into panel settings and reload the bot.
- Verify reachability from the host: curl -sS https://api.telegram.org/bot<TOKEN>/getMe — if this hangs or is reset, fix egress (firewall rule, or route the server through a proxy/region that can reach Telegram).
- Retry once after fixing network: transient DNS/TLS failures self-heal; auth failures never do.
- Confirm system time is correct (TLS cert validation fails on skewed clocks).
Example fix
// before
me, err := b.GetMe(context.Background())
if err != nil {
return fmt.Errorf("API unreachable: %w", err)
}
// after — distinguish auth failure from network failure for the user
me, err := b.GetMe(context.Background())
if err != nil {
if strings.Contains(err.Error(), "401") {
return fmt.Errorf("telegram rejected the token (401): get a fresh token from @BotFather: %w", err)
}
return fmt.Errorf("API unreachable (check server egress to api.telegram.org): %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight reachability check before the bot test (optional, cheap)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if _, err := net.DefaultResolver.LookupHost(ctx, "api.telegram.org"); err != nil {
return fmt.Errorf("panel host cannot resolve api.telegram.org: %w", err)
} Type guard
null
Try / catch
if err := tgbotSvc.TestConnection(); err != nil {
if strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "Unauthorized") {
// token problem: reconfigure, no retry
} else {
// network problem: fix egress, then retry once
}
} Prevention
- Verify token freshness after regenerating tokens in BotFather.
- Ensure the panel host has stable egress to api.telegram.org:443 (curl smoke test in monitoring).
When it happens
Trigger: TestConnection with a syntactically plausible but revoked token (Telegram returns 401), or from a host that cannot reach api.telegram.org — common on servers in regions where Telegram is blocked, or behind an egress firewall without HTTPS proxying.
Common situations: Token regenerated via BotFather after the panel saved the old one; server in a country/ISP blocking Telegram (needs a proxy the panel's bot client doesn't use); transient DNS failure; server clock skew breaking TLS.
Related errors
- telegram bot disabled
- tg_id must be a positive integer
- telegram API test failed: %w
- The current username or password is invalid
- The new username and password are empty
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/a8333a3db81f58c7.
Report an issue: GitHub.