{"record":{"id":"a8333a3db81f58c7","repo":"MHSanaei/3x-ui","slug":"api-unreachable-w","errorCode":null,"errorMessage":"API unreachable: %w","messagePattern":"API unreachable: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/service/tgbot/tgbot_send.go","lineNumber":271,"sourceCode":"\t}\n\tif err := bot.DeleteMessage(context.Background(), &params); err != nil {\n\t\tlogger.Warning(\"Failed to delete message:\", err)\n\t} else {\n\t\tlogger.Info(\"Message deleted successfully\")\n\t}\n}\n\n// TestConnection verifies the bot token is valid and the API is reachable.\nfunc (t *Tgbot) TestConnection() error {\n\ttgBotMutex.Lock()\n\tb := bot\n\ttgBotMutex.Unlock()\n\tif b == nil {\n\t\treturn fmt.Errorf(\"bot not initialized\")\n\t}\n\tme, err := b.GetMe(context.Background())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"API unreachable: %w\", err)\n\t}\n\t_ = me\n\treturn nil\n}\n","sourceCodeStart":253,"sourceCodeEnd":276,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/tgbot/tgbot_send.go#L253-L276","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nme, err := b.GetMe(context.Background())\nif err != nil {\n    return fmt.Errorf(\"API unreachable: %w\", err)\n}\n\n// after — distinguish auth failure from network failure for the user\nme, err := b.GetMe(context.Background())\nif err != nil {\n    if strings.Contains(err.Error(), \"401\") {\n        return fmt.Errorf(\"telegram rejected the token (401): get a fresh token from @BotFather: %w\", err)\n    }\n    return fmt.Errorf(\"API unreachable (check server egress to api.telegram.org): %w\", err)\n}","handlingStrategy":"retry","validationCode":"// Pre-flight reachability check before the bot test (optional, cheap)\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\nif _, err := net.DefaultResolver.LookupHost(ctx, \"api.telegram.org\"); err != nil {\n    return fmt.Errorf(\"panel host cannot resolve api.telegram.org: %w\", err)\n}","typeGuard":"null","tryCatchPattern":"if err := tgbotSvc.TestConnection(); err != nil {\n    if strings.Contains(err.Error(), \"401\") || strings.Contains(err.Error(), \"Unauthorized\") {\n        // token problem: reconfigure, no retry\n    } else {\n        // network problem: fix egress, then retry once\n    }\n}","preventionTips":["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)."],"tags":["telegram","network","api"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}