gohugoio/hugo · error
filepath must be absolute
Error message
filepath must be absolute
What it means
`paths.UrlFromFilename` converts an OS filesystem path into a `file://` URL (code adapted from the Go toolchain). It requires the input to be an absolute path because a relative path cannot be turned into a well-defined file URL, and Windows volume/UNC handling depends on the absolute form. A relative input returns this error immediately.
Source
Thrown at common/paths/url.go:123
// URLEscape escapes unicode letters.
func URLEscape(uri string) string {
// escape unicode letters
u, err := url.Parse(uri)
if err != nil {
panic(err)
}
return u.String()
}
// TrimExt trims the extension from a path..
func TrimExt(in string) string {
return strings.TrimSuffix(in, path.Ext(in))
}
// From https://github.com/golang/go/blob/e0c76d95abfc1621259864adb3d101cf6f1f90fc/src/cmd/go/internal/web/url.go#L45
func UrlFromFilename(filename string) (*url.URL, error) {
if !filepath.IsAbs(filename) {
return nil, fmt.Errorf("filepath must be absolute")
}
// If filename has a Windows volume name, convert the volume to a host and prefix
// per https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.
if vol := filepath.VolumeName(filename); vol != "" {
if strings.HasPrefix(vol, `\\`) {
filename = filepath.ToSlash(filename[2:])
i := strings.IndexByte(filename, '/')
if i < 0 {
// A degenerate case.
// \\host.example.com (without a share name)
// becomes
// file://host.example.com/
return &url.URL{
Scheme: "file",
Host: filename,
Path: "/",View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Resolve the path with `filepath.Abs` (or join it against the project/working dir) before calling `UrlFromFilename`.
- Check where the path originates — config values and CLI args should be absolutized at the boundary.
- In tests, construct paths with `t.TempDir()` or `filepath.Abs` rather than literals.
Example fix
// before
u, err := paths.UrlFromFilename("content/post.md")
// after
abs, _ := filepath.Abs("content/post.md")
u, err := paths.UrlFromFilename(abs) Defensive patterns
Strategy: validation
Validate before calling
if !filepath.IsAbs(p) {
p = filepath.Join(baseDir, p)
} Type guard
func ensureAbs(p, base string) string {
if filepath.IsAbs(p) { return p }
return filepath.Join(base, p)
} Prevention
- Convert paths with filepath.Abs or join against a known base before calling URL-from-filepath helpers
- Never pass user-supplied or config-relative paths straight through; normalize at the boundary
- Beware platform differences: a Windows drive path is not absolute on Linux
When it happens
Trigger: Any internal caller passing a relative path to `UrlFromFilename`, e.g. building source-map or file:// references from a path that wasn't run through `filepath.Abs` first; paths produced from working-directory-relative config values.
Common situations: Running Hugo from an unexpected working directory so a path stays relative; custom tooling or tests calling helpers with `content/post.md` instead of an absolute path; symlinked project layouts where path normalization was skipped.
Related errors
- no filesystem provided
- failed to save file %q:: %w
- failed to resolve output path %q: %w
- failed to copy %q to %q: %w
- target path "%s" exists but is not a directory
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/0eb018c527c52668.json.
Report an issue: GitHub ↗.