gohugoio/hugo · error
failed to parse URL for resource
Error message
failed to parse URL for resource %s: %w
What it means
Wrapped error from `Client.FromRemote` (remote.go:196-198) when `url.Parse(uri)` fails. Hugo requires a syntactically valid URL before doing anything else with the remote resource request. The error from the stdlib `url.Parse` is wrapped with the offending URI for context.
Solutions
- Ensure the URL has an explicit scheme and host (`https://...`).
- URL-encode dynamic path/query segments with `htmlEscape`/`urlquery` before assembling.
- Trim whitespace and strip smart quotes from frontmatter-supplied URLs.
- Pre-validate with a quick `url.Parse` test harness for frontmatter URLs.
Example fix
// template -- before
{{ $r := resources.GetRemote (printf "%s/%s" $base $slug) }}
// after
{{ $r := resources.GetRemote (printf "%s/%s" $base (urlquery $slug)) }} Defensive patterns
Strategy: validation
Validate before calling
import "net/url"
func validateRemoteURL(s string) error {
u, err := url.Parse(s)
if err != nil { return err }
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("URL %q missing scheme or host", s)
}
return nil
} Try / catch
// Template-side guard.
{{ $u := urls.Parse $raw }}
{{ if and $u.Scheme $u.Host }}{{ $r := resources.GetRemote $raw }}{{ end }} Prevention
- Always include `https://` (or `http://`).
- URL-encode dynamic segments via `urlquery`/`htmlEscape`.
- Trim whitespace from frontmatter URL fields.
When it happens
Trigger: Calling `resources.GetRemote` / `FromRemote` with a malformed URL string: unescaped spaces, missing scheme (`example.com/x`), stray control characters, unbalanced brackets, or template interpolation injecting bad characters.
Common situations: Template builds URL via `printf` without escaping user input; missing `http://`/`https://` scheme; copy-paste from a rich-text editor inserting non-breaking spaces; query params with raw `&`/`#`; content frontmatter URL field with leading/trailing whitespace or stray quotes.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to create request for resource
- failed to decode options for resource
- failed to fetch remote resource from
- failed to read remote resource
- invalid timeout for resource
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/de6d2236d793dd62.
Report an issue: GitHub.
Appendix: 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 52c9bd7908)