{"record":{"id":"d58600d33257efd4","repo":"Tencent/WeKnora","slug":"no-adapter-factory-for-platform-s","errorCode":null,"errorMessage":"no adapter factory for platform: %s","messagePattern":"no adapter factory for platform: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/im/service.go","lineNumber":1112,"sourceCode":"\t\tlogger.Warnf(context.Background(), \"[IM] Reload channel %s after %s failed: %v\", channelID, reason, err)\n\t}\n}\n\n// StartChannel creates and registers an adapter for the given channel.\n// For WebSocket channels with Redis available, only one instance acquires\n// the leader lock and opens the connection; other instances periodically\n// retry so they can take over if the leader dies.\nfunc (s *Service) StartChannel(channel *IMChannel) error {\n\tif s.stopped.Load() {\n\t\treturn fmt.Errorf(\"im service is stopped\")\n\t}\n\n\ts.mu.Lock()\n\ts.stopLeaderRetryLocked(channel.ID)\n\tfactory, ok := s.adapterFactories[channel.Platform]\n\tif !ok {\n\t\ts.mu.Unlock()\n\t\treturn fmt.Errorf(\"no adapter factory for platform: %s\", channel.Platform)\n\t}\n\t// Stop existing channel if running\n\tif existing, ok := s.channels[channel.ID]; ok {\n\t\ts.stopChannelLocked(channel.ID, existing)\n\t}\n\ts.mu.Unlock()\n\n\t// For WebSocket / long-poll channels, try leader election to avoid\n\t// duplicate connections. Only one instance should actively poll or\n\t// maintain a persistent connection for each channel.\n\tif (channel.Mode == \"websocket\" || channel.Mode == \"longpoll\") && s.redis != nil {\n\t\tacquired := s.tryAcquireWSLeader(channel.ID)\n\t\tif !acquired {\n\t\t\tlogger.Infof(context.Background(),\n\t\t\t\t\"[IM] Channel %s %s owned by another instance, will retry\", channel.ID, channel.Mode)\n\t\t\ts.scheduleWSLeaderRetry(channel)\n\t\t\treturn nil\n\t\t}","sourceCodeStart":1094,"sourceCodeEnd":1130,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/im/service.go#L1094-L1130","documentation":"StartChannel looks up the platform's adapter factory in s.adapterFactories (populated at service construction via registered factories). If no factory is registered for channel.Platform, the channel cannot be started and this error is returned.","triggerScenarios":"Calling StartChannel (or the dynamic-start path when a message arrives for an unknown channel) with a channel whose Platform string has no registered factory — e.g. typo'd platform name or an adapter package never wired in.","commonSituations":"Misspelled platform in channel config (\"telegramm\", \"whatsap\"); forgetting to import/ register an adapter package (blank import of the factory); new platform added to config before code deploy.","solutions":["Register the adapter factory for that platform when constructing the IM service (e.g. im.NewService(..., telegram.NewFactory(), qqbot.NewFactory()))","Fix the channel's platform string to match a registered platform exactly","Import the adapter package so its factory registration side-effect runs"],"exampleFix":"// before\nsvc := im.NewService(cfg, store) // telegram factory missing\n// after\nsvc := im.NewService(cfg, store, telegram.NewFactory(), qqbot.NewFactory())","handlingStrategy":"validation","validationCode":"known := map[string]bool{\"telegram\":true,\"qqbot\":true /* registered platforms */}\nif !known[channel.Platform] {\n    return fmt.Errorf(\"platform %q is not registered\", channel.Platform)\n}","typeGuard":null,"tryCatchPattern":"if err := svc.StartChannel(ch); err != nil {\n    if strings.HasPrefix(err.Error(), \"no adapter factory\") {\n        log.Printf(\"platform %s not registered; check factory wiring\", ch.Platform)\n    }\n}","preventionTips":["Register every adapter factory at service construction and keep the list in one place","Use constants for platform names instead of free-form strings in configs","Add a startup self-test that starts all configured channels so missing factories fail fast"],"tags":["adapter","platform","registration"],"backgroundTag":"unknown-platform-adapter","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}