chenhg5/cc-connect · error
subscribe: %w
Error message
subscribe: %w
What it means
startWebhook wraps the error from p.subscribe, which registers the webhook URL with the MAX API. This is the inner layer beneath the "max: start webhook" error and indicates the subscription HTTP call itself failed.
Source
Thrown at platform/max/max.go:237
mux.HandleFunc(p.webhookPath, p.webhookHandler)
srv := &http.Server{
Addr: p.webhookListen,
Handler: mux,
ReadHeaderTimeout: 10 * time.Second,
}
// Caller (Start) already holds p.mu, so assign directly — re-locking
// a non-reentrant sync.RWMutex would deadlock.
p.webServer = srv
go func() {
slog.Info("max: webhook listening", "addr", p.webhookListen, "path", p.webhookPath, "url", p.webhookURL)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("max: webhook listener stopped", "err", err)
}
}()
if err := p.subscribe(ctx, p.webhookURL); err != nil {
return fmt.Errorf("subscribe: %w", err)
}
slog.Info("max: webhook subscribed", "url", p.webhookURL)
// MAX has been observed to silently drop the webhook subscription
// server-side without any delivery error. The documented 8h failure
// window does not match the observed cadence (drops every 25–60min),
// so we periodically re-POST the subscription. MAX overwrites the
// existing registration in-place, so re-subscribing is idempotent.
if p.resubscribeInterval > 0 {
go p.resubscribeLoop(ctx)
}
return nil
}
func (p *Platform) resubscribeLoop(ctx context.Context) {
t := time.NewTicker(p.resubscribeInterval)
defer t.Stop()
for {View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped error: for "HTTP 4xx/5xx" inspect the API status and response body.
- Verify the bot token is valid and has permission to manage subscriptions.
- Confirm the webhook URL is publicly reachable over HTTPS from MAX servers.
- Rely on the built-in resubscribe loop for transient drops; only intervene if failures are persistent.
Defensive patterns
Strategy: retry
Validate before calling
// pre-check token validity
resp, err := http.Get("https://botapi.max.ru/me?access_token=" + token)
// err != nil or non-200 → do not attempt webhook setup Try / catch
if err := p.Start(handler); err != nil {
if strings.Contains(err.Error(), "subscribe:") {
// schedule a delayed restart with backoff
time.AfterFunc(backoff, func() { retryStart() })
}
} Prevention
- Use the built-in resubscribe loop rather than manual restarts on transient errors
- Confirm webhook URL reachability and HTTPS before subscribing
- Rotate/validate bot tokens before startup
When it happens
Trigger: Start (or the resubscribe loop) invoking subscribe with a webhook URL that the MAX API rejects: network failure, invalid URL, HTTP 4xx/5xx response, or invalid bot token.
Common situations: Bot token revoked/missing subscription scope, webhook URL not HTTPS or unreachable by MAX servers, transient network outage during a periodic resubscribe.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- HTTP %d: %s
- request usage endpoint: %w
- usage endpoint returned status %d: %s
- decode usage response: %w
- fetch presets: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/0f5253a7c3d17660.
Report an issue: GitHub.