sipeed/picoclaw · error
slack_webhook: at least one webhook target is required
Error message
slack_webhook: at least one webhook target is required
What it means
NewSlackWebhookChannel rejects a slack_webhook channel whose settings have no webhooks entries at all (config key webhooks, a map of SlackWebhookTarget, pkg/config/config.go:743). The channel is outgoing-only and delivers exclusively via Slack incoming webhooks, so an empty map leaves it with nothing to send to; construction fails fast.
Source
Thrown at pkg/channels/slack_webhook/slack_webhook.go:39
const maxTextBlockLength = 3000
// SlackWebhookChannel is an output-only channel that sends messages
// to Slack via Incoming Webhooks using Block Kit formatting.
type SlackWebhookChannel struct {
*channels.BaseChannel
bc *config.Channel
config *config.SlackWebhookSettings
client *http.Client
}
// NewSlackWebhookChannel creates a new Slack webhook channel.
func NewSlackWebhookChannel(
bc *config.Channel,
cfg *config.SlackWebhookSettings,
bus *bus.MessageBus,
) (*SlackWebhookChannel, error) {
if len(cfg.Webhooks) == 0 {
return nil, fmt.Errorf("slack_webhook: at least one webhook target is required")
}
if _, hasDefault := cfg.Webhooks["default"]; !hasDefault {
return nil, fmt.Errorf("slack_webhook: a 'default' webhook target is required")
}
for name, target := range cfg.Webhooks {
webhookURL := target.WebhookURL.String()
if webhookURL == "" {
return nil, fmt.Errorf("slack_webhook: webhook %q has empty webhook_url", name)
}
parsed, err := url.Parse(webhookURL)
if err != nil {
return nil, fmt.Errorf("slack_webhook: webhook %q has invalid URL format: %w", name, err)
}
if !strings.EqualFold(parsed.Scheme, "https") {
return nil, fmt.Errorf("slack_webhook: webhook %q must use HTTPS (got %q)", name, parsed.Scheme)
}View on GitHub (pinned to 49183d7e8d)
Solutions
- Create an incoming webhook in the Slack app (Features > Incoming Webhooks), copy the https://hooks.slack.com/services/... URL, and add it under webhooks with at least a default target (see the companion 'default required' error).
- Check YAML shape: webhooks must be a map directly under the channel's settings with each target having webhook_url.
- If you meant to build a two-way Slack bot, use type: slack with bot/app tokens instead of slack_webhook.
Example fix
# before
channels:
notify:
type: slack_webhook
settings: {} # no webhooks
# after
channels:
notify:
type: slack_webhook
settings:
webhooks:
default:
webhook_url: "https://hooks.slack.com/services/T000/B000/xxxx" Defensive patterns
Strategy: validation
Validate before calling
func slackWebhookTargetsPresent(cfg *config.SlackWebhookSettings) error {
if len(cfg.Webhooks) == 0 {
return fmt.Errorf("add at least one webhooks.<name>.webhook_url (plus 'default')")
}
return nil
} Type guard
// structural guard before channel construction
func hasWebhookMap(v any) bool {
m, ok := v.(map[string]config.SlackWebhookTarget)
return ok && len(m) > 0
} Try / catch
// Go: synchronous constructor error — validate config in deploy pipeline; no runtime catch needed
Prevention
- Create the Slack incoming webhook URL before enabling the channel
- Remember the webhooks map is required even for a single target
- slack_webhook is outgoing-only; choose type: slack for two-way bots
When it happens
Trigger: Creating a channel of type slack_webhook with no webhooks: key in settings; webhooks: {} (empty map); webhook entries indented under the wrong parent so the map parses as empty; using slack_webhook where slack (Socket Mode) was intended.
Common situations: Configuring outgoing notifications but not yet having created the incoming webhook in the Slack app; YAML indentation placing webhook entries under a sibling key; migrating from a single webhook_url field to the webhooks map and leaving it empty.
Related errors
- channel %q: config not found
- teams_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/9245255877f9e37b.
Report an issue: GitHub.