{"record":{"id":"1aa84d987346a837","repo":"chenhg5/cc-connect","slug":"telegram-platform-stopped","errorCode":null,"errorMessage":"telegram: platform stopped","messagePattern":"telegram: platform stopped","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/telegram/telegram.go","lineNumber":220,"sourceCode":"// engine falls back to legacy mode and sends the entire reply (which can be\n// 30k+ characters) in one final p.Send — users perceive it as \"spinner spins\n// for minutes, then a wall of text appears\".\n//\n// To restore the old single-send behavior set progress_style = \"legacy\" in\n// the platform options.\nfunc (p *Platform) ProgressStyle() string {\n\tif p == nil || p.progressStyle == \"\" {\n\t\treturn \"compact\"\n\t}\n\treturn p.progressStyle\n}\n\nfunc (p *Platform) Start(handler core.MessageHandler) error {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\n\tif p.stopping {\n\t\treturn fmt.Errorf(\"telegram: platform stopped\")\n\t}\n\tif p.newBot == nil {\n\t\tp.newBot = defaultNewBot\n\t}\n\tif p.newBackoffTimer == nil {\n\t\tp.newBackoffTimer = func(d time.Duration) backoffTimer {\n\t\t\treturn &stdlibBackoffTimer{Timer: time.NewTimer(d)}\n\t\t}\n\t}\n\tif p.newTypingTicker == nil {\n\t\tp.newTypingTicker = func(d time.Duration) typingTicker {\n\t\t\treturn &stdlibTypingTicker{Ticker: time.NewTicker(d)}\n\t\t}\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tp.handler = handler\n\tp.cancel = cancel","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/telegram/telegram.go#L202-L238","documentation":"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.","triggerScenarios":"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().","commonSituations":"Engine restart logic calling Start on a stopped platform; config reload code reusing instances; a supervisor retrying Start after Stop during application exit.","solutions":["Create a fresh Platform via telegram.New(opts) instead of calling Start on a stopped instance","Ensure Start is called exactly once per Platform instance, before Stop","If implementing restart, gate the retry on whether the platform is stopping and reconstruct otherwise"],"exampleFix":"// before\nif err := p.Start(handler); err != nil { ... } // p was already stopped\n// after\nplatform, err := telegram.New(opts)\nif err != nil { return err }\nreturn platform.Start(handler)","handlingStrategy":"try-catch","validationCode":"// ensure not reusing a stopped instance: construct fresh\nplat, err := telegram.New(opts)\nif err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := plat.Start(handler); err != nil {\n    if strings.Contains(err.Error(), \"platform stopped\") {\n        plat, err = telegram.New(opts)\n        if err != nil { return err }\n        return plat.Start(handler)\n    }\n    return err\n}","preventionTips":["Call Start once per Platform instance","Rebuild the platform (New) for restarts instead of reusing instances","Stop-then-Start on the same instance is not supported — treat Platform as single-use"],"tags":["telegram","lifecycle","shutdown","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}