gohugoio/hugo · error
cannot determine BaseURL for protocol %q
Error message
cannot determine BaseURL for protocol %q
What it means
`BaseURL.WithProtocol` rewrites the scheme of the site's baseURL, supporting both full protocols (`webcal://`) and opaque ones (`mailto:`). An opaque protocol (ending in `:` without `//`) requires the underlying URL to have an opaque part; if the current baseURL has none, Hugo cannot construct a meaningful URL and returns this error.
Source
Thrown at common/urls/baseURL.go:72
func (b BaseURL) WithProtocol(protocol string) (BaseURL, error) {
u := b.URL()
scheme := protocol
isFullProtocol := strings.HasSuffix(scheme, "://")
isOpaqueProtocol := strings.HasSuffix(scheme, ":")
if isFullProtocol {
scheme = strings.TrimSuffix(scheme, "://")
} else if isOpaqueProtocol {
scheme = strings.TrimSuffix(scheme, ":")
}
u.Scheme = scheme
if isFullProtocol && u.Opaque != "" {
u.Opaque = "//" + u.Opaque
} else if isOpaqueProtocol && u.Opaque == "" {
return BaseURL{}, fmt.Errorf("cannot determine BaseURL for protocol %q", protocol)
}
return newBaseURLFromURL(u)
}
func (b BaseURL) WithPort(port int) (BaseURL, error) {
u := b.URL()
u.Host = u.Hostname() + ":" + strconv.Itoa(port)
return newBaseURLFromURL(u)
}
// URL returns a copy of the internal URL.
// The copy can be safely used and modified.
func (b BaseURL) URL() *url.URL {
c := *b.url
return &c
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Use the full `scheme://` form in the output format's `protocol` setting (e.g. `webcal://`, not `webcal:`).
- If an opaque scheme is genuinely intended, ensure the baseURL is itself opaque; otherwise reconsider the design.
- Check `hugo config` for the offending `protocol` value under outputFormats.
Example fix
# before (hugo.toml) [outputFormats.Calendar] protocol = "webcal:" # after [outputFormats.Calendar] protocol = "webcal://"
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(baseURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("baseURL must be http(s), got %q", baseURL)
} Try / catch
if err != nil {
// report the unsupported scheme and fix baseURL in config; do not retry
} Prevention
- Set baseURL in config with an explicit http:// or https:// scheme
- Avoid exotic schemes (ftp, file, custom) in baseURL; Hugo only maps ports for known protocols
- Validate baseURL parse + scheme during config load in CI
When it happens
Trigger: An output format or media type configured with a `protocol` like `mailto:` or `tel:` applied to a normal hierarchical baseURL (e.g. `https://example.com/`) — `WithProtocol("mailto:")` on such a URL has no opaque component to carry the address.
Common situations: Custom `[outputFormats]` entries setting `protocol = "something:"` when `something://` was intended; experimenting with webcal/mailto protocols on standard site baseURLs; typo dropping the slashes from a protocol value.
Related errors
- unknown output format %q for kind %q
- unknown default output format %q
- errPermalinkAttributeUnknown
- OutputFormat with key %q not found
- language %q not found
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/35e5f9b54a6493ab.json.
Report an issue: GitHub ↗.