sipeed/picoclaw · error

slack_webhook: webhook %q must use HTTPS (got %q)

Error message

slack_webhook: webhook %q must use HTTPS (got %q)

What it means

NewSlackWebhookChannel enforces that every webhook_url uses the https scheme (case-insensitive via strings.EqualFold). Slack incoming webhooks are only served over HTTPS; an http:// URL is rejected at construction. This is also a data-protection guard: webhook URLs are bearer secrets, and sending them over plain HTTP would leak them.

Source

Thrown at pkg/channels/slack_webhook/slack_webhook.go:56

	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)
		}
	}

	base := channels.NewBaseChannel(
		"slack_webhook",
		cfg,
		bus,
		[]string{"*"},
		channels.WithMaxMessageLength(40000),
	)

	return &SlackWebhookChannel{
		BaseChannel: base,
		bc:          bc,
		config:      cfg,
		client: &http.Client{
			Timeout: 30 * time.Second,
		},

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Use the exact https://hooks.slack.com/services/... URL Slack shows for the incoming webhook.
  2. If routing through an internal proxy, terminate TLS before the proxy and still configure the https:// form.
  3. Add the scheme when it is missing: https://hooks.slack.com/... — the error message echoes the scheme it saw (empty means no scheme).

Example fix

# before
webhook_url: "http://hooks.slack.com/services/T000/B000/abc"

# after
webhook_url: "https://hooks.slack.com/services/T000/B000/abc"
Defensive patterns

Strategy: validation

Validate before calling

func isHTTPSWebhook(raw string) bool {
    u, err := url.Parse(strings.TrimSpace(raw))
    return err == nil && strings.EqualFold(u.Scheme, "https")
}

Try / catch

// Go: construction-time error; the message echoes the offending scheme — fix the URL, no runtime handling

Prevention

When it happens

Trigger: webhook_url starting with http:// (including Http:// variants — EqualFold is case-insensitive but only https passes); a URL missing its scheme entirely ("hooks.slack.com/services/...") parses with an empty scheme and also fails; internal proxy URLs configured with http://.

Common situations: Copying an http:// link from old documentation or a chat message; hand-typing the URL and omitting the scheme or the s; pointing at an internal HTTPS-terminating proxy and forgetting to update the scheme after enabling TLS; misconfigured copy of the Slack URL from a legacy integration page.

Related errors


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