sipeed/picoclaw · error
teams_webhook: at least one webhook target is required
Error message
teams_webhook: at least one webhook target is required
What it means
NewTeamsWebhookChannel rejects a teams_webhook channel whose settings contain no webhook targets (config key webhooks, map[string]TeamsWebhookTarget, pkg/config/config.go:721). Like slack_webhook, the channel is outgoing-only and delivers exclusively via Microsoft Teams Workflows/Connectors incoming webhooks, so an empty map leaves nothing to send to and construction fails fast.
Source
Thrown at pkg/channels/teams_webhook/teams_webhook.go:67
// TeamsWebhookChannel is an output-only channel that sends messages
// to Microsoft Teams via Power Automate workflow webhooks.
// Multiple webhook targets can be configured and selected via ChatID.
type TeamsWebhookChannel struct {
*channels.BaseChannel
bc *config.Channel
config *config.TeamsWebhookSettings
client teamsMessageSender
}
// NewTeamsWebhookChannel creates a new Teams webhook channel.
func NewTeamsWebhookChannel(
bc *config.Channel,
cfg *config.TeamsWebhookSettings,
bus *bus.MessageBus,
) (*TeamsWebhookChannel, error) {
if len(cfg.Webhooks) == 0 {
return nil, fmt.Errorf("teams_webhook: at least one webhook target is required")
}
// Require "default" webhook target
if _, hasDefault := cfg.Webhooks["default"]; !hasDefault {
return nil, fmt.Errorf("teams_webhook: a 'default' webhook target is required")
}
// Validate all webhook targets have valid HTTPS URLs
for name, target := range cfg.Webhooks {
webhookURL := target.WebhookURL.String()
if webhookURL == "" {
return nil, fmt.Errorf("teams_webhook: webhook %q has empty webhook_url", name)
}
parsed, err := url.Parse(webhookURL)
if err != nil {
return nil, fmt.Errorf("teams_webhook: webhook %q has invalid URL: %w", name, err)
}
if !strings.EqualFold(parsed.Scheme, "https") {View on GitHub (pinned to 49183d7e8d)
Solutions
- Create an incoming webhook in Teams (channel > Workflows/Connectors > incoming webhook) and copy the https://...webhook.office.com/... (or outlook.office365.com/webhook/...) URL.
- Add it under webhooks with at least a default target — the constructor also requires a 'default' key and HTTPS URLs for every target.
- Verify YAML nesting: webhooks sits under the channel's settings, each target is a map key with webhook_url.
- If a full Teams bot (messages in, not just notifications out) is needed, use the teams channel type instead.
Example fix
# before
channels:
msteams:
type: teams_webhook
settings: {}
# after
channels:
msteams:
type: teams_webhook
settings:
webhooks:
default:
webhook_url: "https://prod-XX.region.logic.azure.com/workflows/.../triggers/manual/paths/invoke" Defensive patterns
Strategy: validation
Validate before calling
func teamsWebhookTargetsPresent(cfg *config.TeamsWebhookSettings) error {
if len(cfg.Webhooks) == 0 {
return fmt.Errorf("add webhooks.default.webhook_url (Teams Workflows URL) before enabling teams_webhook")
}
return nil
} Type guard
// structural guard before construction
func hasTeamsWebhookMap(v any) bool {
m, ok := v.(map[string]config.TeamsWebhookTarget)
return ok && len(m) > 0
} Try / catch
// Go: synchronous constructor error — validate config in the deploy pipeline; nothing to catch at message-send time
Prevention
- Create the Teams Workflows/connector webhook URL first, then configure
- Remember the 'default' target is also mandatory (companion validation)
- teams_webhook is notification-only; pick the teams channel type for two-way bots
When it happens
Trigger: Creating a channel of type teams_webhook with no webhooks: key, webhooks: {}, or entries indented under the wrong parent key so the map decodes empty; using teams_webhook when a two-way Teams bot channel was intended.
Common situations: Not having created the Teams incoming webhook URL (Power Automate Workflows 'When a webhook request is received' or legacy Office 365 connector) before configuring the channel; migrating from a single-url field to the webhooks map; YAML indentation mistakes after copy-pasting a slack_webhook block as a template.
Related errors
- channel %q: config not found
- slack_webhook: at least one webhook target is required
- must be in range 1-65535
- failed to load MCP servers: %w
- failed to create discord session: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/eb3009819f5d402f.
Report an issue: GitHub.