gohugoio/hugo · error
failed to parse URL for resource %s: %w
Error message
failed to parse URL for resource %s: %w
What it means
`resources.GetRemote` (Client.FromRemote) first parses the given URI with `url.Parse`. If the string is not a syntactically valid URL, Hugo fails fast with this wrapped parse error rather than attempting a request. Note that `url.Parse` is lenient, so this usually means genuinely malformed input like invalid control characters or bad percent-encoding.
Source
Thrown at resources/resource_factories/create/remote.go:198
if time.Since(lastChange) < 10*time.Second {
// The user is typing, check more often.
return 0, nil
}
// Increase the interval to avoid hammering the server.
interval += 1 * time.Second
return interval, nil
},
})
}
// FromRemote expects one or n-parts of a URL to a resource
// If you provide multiple parts they will be joined together to the final URL.
func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resource, error) {
rURL, err := url.Parse(uri)
if err != nil {
return nil, fmt.Errorf("failed to parse URL for resource %s: %w", uri, err)
}
method := "GET"
if s, _, ok := hmaps.LookupEqualFold(optionsm, "method"); ok {
method = strings.ToUpper(s.(string))
}
isHeadMethod := method == "HEAD"
optionsm = maps.Clone(optionsm)
// Extract timeout before computing cache keys: it only affects fetch behaviour,
// not the cached content, so it must not influence the cache key.
var perRequestTimeout time.Duration
if v, k, ok := hmaps.LookupEqualFold(optionsm, "timeout"); ok {
d, err := cast.ToDurationE(v)
if err != nil {
return nil, fmt.Errorf("invalid timeout for resource %s: %w", uri, err)
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Trim and validate the URL before use: `{{ $u := trim $url " \n" }}`.
- Properly encode query parameters (e.g. `querify` or `urlquery`) instead of concatenating raw values.
- Print the exact string passed (`warnf "url=%q" $url`) to spot hidden whitespace or bad percent-escapes in the data source.
Example fix
{{/* before */}}
{{ $r := resources.GetRemote (printf "%s?q=%s" .Params.api .Params.query) }}
{{/* after */}}
{{ $u := printf "%s?%s" (trim .Params.api " \n") (querify "q" .Params.query) }}
{{ $r := resources.GetRemote $u }} Defensive patterns
Strategy: validation
Validate before calling
{{ $url := .Params.remote_url }}
{{ $u := urls.Parse $url }}
{{ if or (not $u.Scheme) (not $u.Host) }}
{{ errorf "invalid remote resource URL: %q" $url }}
{{ end }}
{{ $r := resources.GetRemote $url }} Prevention
- Validate URLs from front matter/data files with urls.Parse before resources.GetRemote
- URL-encode query parameters and spaces; raw user strings often contain illegal characters
- Require absolute URLs with an explicit https scheme in content that feeds GetRemote
When it happens
Trigger: Calling `resources.GetRemote $url` in a template where `$url` contains invalid characters (spaces, newlines, unescaped `%` sequences like `%zz`, control chars), or where multiple URL parts were joined/interpolated incorrectly (e.g. `printf` with stray whitespace from front matter).
Common situations: URLs read from front matter or data files with trailing newlines/spaces, hand-built query strings with unencoded values, CSV/JSON data containing malformed URLs, or template string concatenation inserting a literal `\n`.
Related errors
- failed to decode options for resource %s: %w
- failed to create request for resource %s: %w
- error building site: %w
- failed to detect format from content
- failed to detect target data serialization format
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/de6d2236d793dd62.json.
Report an issue: GitHub ↗.