sipeed/picoclaw · error

channel %s not found

Error message

channel %s not found

What it means

The reaction tool found the channel manager but channels.Manager.GetChannel(name) returned false for the name the model passed. GetChannel (pkg/channels/manager.go:1871) is a case-sensitive map lookup over channels registered via RegisterChannel, so the argument must exactly match a registered channel name. The channel argument comes straight from the LLM, so hallucinated, stale, or misspelled names fail here.

Source

Thrown at pkg/agent/agent_init.go:229

				}
				if al.channelManager != nil && channel != "" {
					return al.channelManager.SendMessage(ctx, outboundMessage)
				}
				pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second)
				defer pubCancel()
				return msgBus.PublishOutbound(pubCtx, outboundMessage)
			})
			agent.Tools.Register(messageTool)
		}
		if cfg.Tools.IsToolEnabled("reaction") {
			reactionTool := tools.NewReactionTool()
			reactionTool.SetReactionCallback(func(ctx context.Context, channel, chatID, messageID string) error {
				if al.channelManager == nil {
					return fmt.Errorf("channel manager not configured")
				}
				ch, ok := al.channelManager.GetChannel(channel)
				if !ok {
					return fmt.Errorf("channel %s not found", channel)
				}
				rc, ok := ch.(channels.ReactionCapable)
				if !ok {
					return fmt.Errorf("channel %s does not support reactions", channel)
				}
				_, err := rc.ReactToMessage(ctx, chatID, messageID)
				return err
			})
			agent.Tools.Register(reactionTool)
		}

		// Send file tool (outbound media via MediaStore — store injected later by SetMediaStore)
		if cfg.Tools.IsToolEnabled("send_file") {
			sendFileTool := tools.NewSendFileTool(
				agent.Workspace,
				cfg.Agents.Defaults.RestrictToWorkspace,
				cfg.Agents.Defaults.GetMaxMediaSize(),
				nil,

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. List registered names via cm.GetStatus() and correct the tool argument or the config so they match exactly (case-sensitive)
  2. Enable the channel in config (channels.<name>.enabled=true with valid credentials) and restart picoclaw
  3. If the channel was renamed, restart so RegisterChannel sees the new key, and update prompts that hard-code channel names
  4. Give the model the valid channel list in its system prompt so it stops guessing

Example fix

// config/config.json — before
"channels": { "telegram": { "enabled": false } }

// after
"channels": { "telegram": { "enabled": true, "token": "..." } }
Defensive patterns

Strategy: validation

Validate before calling

for name := range cm.GetStatus() {
    log.Printf("registered channel: %s", name)
}
ch, ok := cm.GetChannel(channelName)
if !ok {
    return fmt.Errorf("channel %q not registered; fix config or tool argument", channelName)
}
_ = ch // safe to proceed with the reaction

Prevention

When it happens

Trigger: The agent calls the reaction tool with channel="Telegram" while the registered name is "telegram"; the channel was renamed/removed in config without a restart; the channel failed init and was never registered into the manager's map.

Common situations: Case mismatch between tool argument and registered name; renaming a channel in config while agent prompts or session history still reference the old name; channel disabled (enabled=false) in config; model typos.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/161afd3ac4d7956d. Report an issue: GitHub.