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

  1. Resolve the path with `filepath.Abs` (or join it against the project/working dir) before calling `UrlFromFilename`.
  2. Check where the path originates — config values and CLI args should be absolutized at the boundary.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/0eb018c527c52668.json. Report an issue: GitHub ↗.