henrygd/beszel · error
error parsing URL: %v
Error message
error parsing URL: %v
What it means
SendShoutrrrAlert sends alerts via a Shoutrrr service URL (e.g. discord://token@id, smtp://...). The URL is parsed with url.Parse first; on failure the raw error is wrapped as `error parsing URL: %v`, meaning the notification URL string is malformed.
Source
Thrown at internal/alerts/alerts.go:256
From: mail.Address{
Address: am.hub.Settings().Meta.SenderAddress,
Name: am.hub.Settings().Meta.SenderName,
},
}
err = am.hub.NewMailClient().Send(&message)
if err != nil {
return err
}
am.hub.Logger().Info("Sent email alert", "to", message.To, "subj", message.Subject)
return nil
}
// SendShoutrrrAlert sends an alert via a Shoutrrr URL
func (am *AlertManager) SendShoutrrrAlert(notificationUrl, title, message, link, linkText string) error {
// Parse the URL
parsedURL, err := url.Parse(notificationUrl)
if err != nil {
return fmt.Errorf("error parsing URL: %v", err)
}
scheme := parsedURL.Scheme
queryParams := parsedURL.Query()
// Add title
if _, ok := supportsTitle[scheme]; ok {
queryParams.Add("title", title)
} else if scheme == "mattermost" {
// use markdown title for mattermost
message = "##### " + title + "\n\n" + message
} else if scheme == "generic" && queryParams.Has("template") {
// add title as property if using generic with template json
titleKey := queryParams.Get("titlekey")
if titleKey == "" {
titleKey = "title"
}
queryParams.Add("$"+titleKey, title)
} else {View on GitHub (pinned to b38fb7dafa)
Solutions
- Percent-encode reserved characters in the URL's userinfo portion: `%` → %25, `@` → %40, spaces → %20.
- Log/inspect the exact notificationUrl value; strip surrounding whitespace, quotes, and invisible characters.
- Use shoutrrr's URL generator (`shoutrrr generate <service>`) instead of hand-assembling the URL.
- If a password contains reserved characters, escape it or move credentials to a mechanism that doesn't require URL encoding.
Example fix
// before notificationUrl := "discord://my@token@123456" // after notificationUrl := "discord://my%40token@123456" // @ in token percent-encoded
Defensive patterns
Strategy: validation
Validate before calling
// validate the notification URL before sending
if _, err := url.Parse(notificationUrl); err != nil {
return fmt.Errorf("invalid shoutrrr URL %q: %w", notificationUrl, err)
} Type guard
func validShoutrrrURL(u string) bool {
parsed, err := url.Parse(u)
return err == nil && parsed.Scheme != ""
} Try / catch
if err := am.SendShoutrrrAlert(notificationUrl, title, msg, link, linkText); err != nil {
if strings.HasPrefix(err.Error(), "error parsing URL") {
log.Printf("check notification URL encoding for %%, @, spaces: %v", err)
} else {
return err
}
} Prevention
- Percent-encode tokens/passwords (%25, %40, %20).
- Generate URLs with `shoutrrr generate` instead of by hand.
- Trim whitespace/quotes from config values before use.
- Test the URL once at startup with SendTestNotification.
When it happens
Trigger: url.Parse(notificationUrl) errors: invalid characters (unescaped spaces, control chars, a stray `%` like `100%`), or misplaced reserved characters such as an extra `@` or unescaped password, e.g. `discord://my@token@123456`.
Common situations: Users paste service URLs into config/env with unescaped special characters in tokens/passwords; template placeholders left unrendered; smart quotes or trailing whitespace from copy/paste.
Related errors
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/5aff131dba708185.
Report an issue: GitHub.