amir20/dozzle · error
invalid webhook URL
Error message
invalid webhook URL: %w
What it means
NewWebhookDispatcher validates the raw webhook URL with url.Parse before constructing the dispatcher. If Go's URL parser cannot parse the string at all (e.g. control characters, malformed percent-encoding), it returns this wrapped error and no dispatcher is created.
Solutions
- Inspect the wrapped parse error for the exact offending position
- Re-enter the URL cleanly, trimming whitespace and control characters
- Percent-encode special characters properly (use url.PathEscape / QueryEscape on components)
- If the URL comes from YAML/env, check for line-folding or BOM artifacts
Example fix
// before
NewWebhookDispatcher("hook", "https://example.com/hook?x=100%", "", nil)
// after
NewWebhookDispatcher("hook", "https://example.com/hook?x=100%25", "", nil) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(rawURL))
if err != nil {
return fmt.Errorf("webhook URL is not parseable: %w", err)
} Type guard
func validURL(raw string) bool {
_, err := url.Parse(strings.TrimSpace(raw))
return err == nil
} Try / catch
d, err := NewWebhookDispatcher(name, rawURL, tpl, headers)
if err != nil {
return fmt.Errorf("webhook config invalid: %w", err)
} Prevention
- Trim and sanitize URLs from UI/config input before constructing dispatchers
- Avoid manual string concatenation into URLs; escape components
- Validate URLs at config-save time in your own UI
When it happens
Trigger: Calling NewWebhookDispatcher (or createDispatcher for a webhook destination) with a rawURL string that net/url.Parse rejects, such as one containing invalid percent escapes or control bytes.
Common situations: Webhook URL pasted into the UI with stray whitespace/newlines or copied from a rich-text source; unescaped '%' characters; config file YAML values containing invisible characters.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- invalid webhook URL scheme
- failed to parse template
- user has an invalid filter
- Failed to save alert
- Toast id is required when once is true
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/f387c0b2ed094074.
Report an issue: GitHub.
Appendix: source
Thrown at internal/notification/dispatcher/webhook.go:165
// UserAgent is set by the application at startup
var UserAgent = "Dozzle/head"
// WebhookDispatcher sends notifications to a webhook URL
type WebhookDispatcher struct {
Name string
URL string
Template *template.Template
TemplateText string // Original template string for serialization
Headers map[string]string
client *http.Client
}
// NewWebhookDispatcher creates a new webhook dispatcher
// If templateStr is empty, the notification will be marshaled as JSON directly
func NewWebhookDispatcher(name, rawURL, templateStr string, headers map[string]string) (*WebhookDispatcher, error) {
parsed, err := url.Parse(rawURL)
if err != nil {
return nil, fmt.Errorf("invalid webhook URL: %w", err)
}
if scheme := strings.ToLower(parsed.Scheme); scheme != "http" && scheme != "https" {
return nil, fmt.Errorf("invalid webhook URL scheme %q: only http and https are allowed", parsed.Scheme)
}
w := &WebhookDispatcher{
Name: name,
URL: rawURL,
TemplateText: templateStr,
Headers: headers,
client: &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
DialContext: safeDialContext,
TLSHandshakeTimeout: 10 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},View on GitHub (pinned to d9463cbe21)