chenhg5/cc-connect · error

telegram: platform stopped

Error message

telegram: platform stopped

What it means

Start() refuses to begin the Telegram polling loop if the platform is already in the stopping state. This guard prevents starting goroutines/bots during shutdown, which would leak resources or race with teardown.

Source

Thrown at platform/telegram/telegram.go:220

// engine falls back to legacy mode and sends the entire reply (which can be
// 30k+ characters) in one final p.Send — users perceive it as "spinner spins
// for minutes, then a wall of text appears".
//
// To restore the old single-send behavior set progress_style = "legacy" in
// the platform options.
func (p *Platform) ProgressStyle() string {
	if p == nil || p.progressStyle == "" {
		return "compact"
	}
	return p.progressStyle
}

func (p *Platform) Start(handler core.MessageHandler) error {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.stopping {
		return fmt.Errorf("telegram: platform stopped")
	}
	if p.newBot == nil {
		p.newBot = defaultNewBot
	}
	if p.newBackoffTimer == nil {
		p.newBackoffTimer = func(d time.Duration) backoffTimer {
			return &stdlibBackoffTimer{Timer: time.NewTimer(d)}
		}
	}
	if p.newTypingTicker == nil {
		p.newTypingTicker = func(d time.Duration) typingTicker {
			return &stdlibTypingTicker{Ticker: time.NewTicker(d)}
		}
	}

	ctx, cancel := context.WithCancel(context.Background())
	p.handler = handler
	p.cancel = cancel

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Create a fresh Platform via telegram.New(opts) instead of calling Start on a stopped instance
  2. Ensure Start is called exactly once per Platform instance, before Stop
  3. If implementing restart, gate the retry on whether the platform is stopping and reconstruct otherwise

Example fix

// before
if err := p.Start(handler); err != nil { ... } // p was already stopped
// after
platform, err := telegram.New(opts)
if err != nil { return err }
return platform.Start(handler)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure not reusing a stopped instance: construct fresh
plat, err := telegram.New(opts)
if err != nil { return err }

Try / catch

if err := plat.Start(handler); err != nil {
    if strings.Contains(err.Error(), "platform stopped") {
        plat, err = telegram.New(opts)
        if err != nil { return err }
        return plat.Start(handler)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Start(handler) after Stop() was called (or while shutdown is in progress), e.g. a restart path that reuses the old Platform instance instead of constructing a new one via telegram.New().

Common situations: Engine restart logic calling Start on a stopped platform; config reload code reusing instances; a supervisor retrying Start after Stop during application exit.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/1aa84d987346a837. Report an issue: GitHub.