gohugoio/hugo · error

invalid Page received in Ref

Error message

invalid Page received in Ref

What it means

The `ref` template function requires its first argument to implement Hugo's RefLinker interface (a Page). If the value passed as the page context isn't a Page — e.g. a string, dict, or nil — this error is returned before any ref resolution happens.

Source

Thrown at tpl/urls/urls.go:96

	}
	return ns.deps.PathSpec.URLize(ss), nil
}

// Anchorize creates sanitized anchor name version of the string s that is compatible
// with how your configured markdown renderer does it.
func (ns *Namespace) Anchorize(s any) (string, error) {
	ss, err := cast.ToStringE(s)
	if err != nil {
		return "", err
	}
	return ns.deps.ContentSpec.SanitizeAnchorName(ss), nil
}

// Ref returns the absolute URL path to a given content item from Page p.
func (ns *Namespace) Ref(p any, args any) (string, error) {
	pp, ok := p.(urls.RefLinker)
	if !ok {
		return "", errors.New("invalid Page received in Ref")
	}
	argsm, err := ns.refArgsToMap(args)
	if err != nil {
		return "", err
	}
	s, err := pp.Ref(argsm)
	return s, err
}

// RelRef returns the relative URL path to a given content item from Page p.
func (ns *Namespace) RelRef(p any, args any) (string, error) {
	pp, ok := p.(urls.RefLinker)
	if !ok {
		return "", errors.New("invalid Page received in RelRef")
	}
	argsm, err := ns.refArgsToMap(args)
	if err != nil {
		return "", err

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Pass a real Page as the first argument: `{{ ref page "about.md" }}` (Hugo's global `page`) or `{{ ref .Page "about.md" }}` in shortcodes.
  2. In partials receiving a dict context, include the page: `{{ partial "x" (dict "page" .) }}` then `{{ ref .page "target" }}`.
  3. Check argument order — the Page comes first, then the ref target.

Example fix

{{/* before, in a shortcode */}}
{{ ref . "about.md" }}
{{/* after */}}
{{ ref .Page "about.md" }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{/* ref must be called with a Page as context */}}
{{ with .Page }}{{ ref . "/blog/post" }}{{ end }}

Type guard

{{/* narrow to a real Page before calling ref */}}
{{ if reflect.IsMap . | not }}{{ with .Page }}{{ $url := ref . "/docs/intro" }}{{ end }}{{ end }}

Try / catch

{{ with try (ref $page "/docs/intro") }}
  {{ with .Err }}{{ warnf "ref failed: %s" . }}{{ end }}
{{ end }}

Prevention

When it happens

Trigger: `{{ ref "page" "about.md" }}` where the first arg is a string instead of a Page, `{{ ref $someDict "x" }}`, or calling `ref .` inside a shortcode/partial where `.` is the shortcode/partial context rather than a Page.

Common situations: Inside partials where the passed context is a dict (use the `page` global or pass the Page explicitly); inside shortcodes forgetting `.Page` (`{{ ref .Page "x" }}` not `{{ ref . "x" }}`); argument order confusion putting the target path first.

Related errors


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