{"record":{"id":"0cc93675c8c5ae46","repo":"sipeed/picoclaw","slug":"slack-webhook-a-default-webhook-target-is-requi","errorCode":null,"errorMessage":"slack_webhook: a 'default' webhook target is required","messagePattern":"slack_webhook: a 'default' webhook target is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/slack_webhook/slack_webhook.go","lineNumber":43,"sourceCode":"type SlackWebhookChannel struct {\n\t*channels.BaseChannel\n\tbc     *config.Channel\n\tconfig *config.SlackWebhookSettings\n\tclient *http.Client\n}\n\n// NewSlackWebhookChannel creates a new Slack webhook channel.\nfunc NewSlackWebhookChannel(\n\tbc *config.Channel,\n\tcfg *config.SlackWebhookSettings,\n\tbus *bus.MessageBus,\n) (*SlackWebhookChannel, error) {\n\tif len(cfg.Webhooks) == 0 {\n\t\treturn nil, fmt.Errorf(\"slack_webhook: at least one webhook target is required\")\n\t}\n\n\tif _, hasDefault := cfg.Webhooks[\"default\"]; !hasDefault {\n\t\treturn nil, fmt.Errorf(\"slack_webhook: a 'default' webhook target is required\")\n\t}\n\n\tfor name, target := range cfg.Webhooks {\n\t\twebhookURL := target.WebhookURL.String()\n\t\tif webhookURL == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"slack_webhook: webhook %q has empty webhook_url\", name)\n\t\t}\n\t\tparsed, err := url.Parse(webhookURL)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"slack_webhook: webhook %q has invalid URL format: %w\", name, err)\n\t\t}\n\t\tif !strings.EqualFold(parsed.Scheme, \"https\") {\n\t\t\treturn nil, fmt.Errorf(\"slack_webhook: webhook %q must use HTTPS (got %q)\", name, parsed.Scheme)\n\t\t}\n\t}\n\n\tbase := channels.NewBaseChannel(\n\t\t\"slack_webhook\",","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/slack_webhook/slack_webhook.go#L25-L61","documentation":"NewSlackWebhookChannel requires that the webhooks map contains a key literally named \"default\". The default target is the fallback used when an outbound message's ChatID names an unknown target (the code logs 'Unknown target, falling back to default' and uses Webhooks[\"default\"]). Without it, fallback sends would panic or fail, so construction refuses.","triggerScenarios":"webhooks populated with custom names (team-a, ops, etc.) but no default entry; the fallback map lookup c.config.Webhooks[\"default\"] would otherwise return a zero-value target at send time.","commonSituations":"Copying an example config that only shows named targets; renaming 'default' to something descriptive; deleting the default entry after adding named targets while messages still arrive without an explicit target.","solutions":["Add a default: entry under webhooks with a valid https://hooks.slack.com/services/... URL.","Point default at your primary webhook if you have several targets; named targets remain addressable via ChatID.","Keep the literal lowercase key 'default' — it is matched exactly, not case-insensitively."],"exampleFix":"# before\nsettings:\n  webhooks:\n    ops:\n      webhook_url: \"https://hooks.slack.com/services/T/B/ops\"\n\n# after\nsettings:\n  webhooks:\n    default:\n      webhook_url: \"https://hooks.slack.com/services/T/B/main\"  # fallback\n    ops:\n      webhook_url: \"https://hooks.slack.com/services/T/B/ops\"","handlingStrategy":"validation","validationCode":"func hasDefaultWebhook(webhooks map[string]config.SlackWebhookTarget) bool {\n    t, ok := webhooks[\"default\"]\n    return ok && t.WebhookURL.String() != \"\"\n}","typeGuard":"// exact-key guard\nfunc defaultTarget(webhooks map[string]config.SlackWebhookTarget) (config.SlackWebhookTarget, bool) {\n    t, ok := webhooks[\"default\"]\n    return t, ok // key match is case-sensitive\n}","tryCatchPattern":"// Go: if err contains \"'default' webhook target is required\" -> add webhooks.default.webhook_url; construction-time only","preventionTips":["Always configure webhooks.default first, then named targets","The key must be the literal lowercase 'default'","Keep default pointed at a webhook you monitor — fallbacks land there"],"tags":["slack-webhook","config","webhook","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}