{"id":"7ca3394c86cb2fbc","repo":"gohugoio/hugo","slug":"invalid-page-received-in-ref","errorCode":null,"errorMessage":"invalid Page received in Ref","messagePattern":"invalid Page received in Ref","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/urls/urls.go","lineNumber":96,"sourceCode":"\t}\n\treturn ns.deps.PathSpec.URLize(ss), nil\n}\n\n// Anchorize creates sanitized anchor name version of the string s that is compatible\n// with how your configured markdown renderer does it.\nfunc (ns *Namespace) Anchorize(s any) (string, error) {\n\tss, err := cast.ToStringE(s)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn ns.deps.ContentSpec.SanitizeAnchorName(ss), nil\n}\n\n// Ref returns the absolute URL path to a given content item from Page p.\nfunc (ns *Namespace) Ref(p any, args any) (string, error) {\n\tpp, ok := p.(urls.RefLinker)\n\tif !ok {\n\t\treturn \"\", errors.New(\"invalid Page received in Ref\")\n\t}\n\targsm, err := ns.refArgsToMap(args)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\ts, err := pp.Ref(argsm)\n\treturn s, err\n}\n\n// RelRef returns the relative URL path to a given content item from Page p.\nfunc (ns *Namespace) RelRef(p any, args any) (string, error) {\n\tpp, ok := p.(urls.RefLinker)\n\tif !ok {\n\t\treturn \"\", errors.New(\"invalid Page received in RelRef\")\n\t}\n\targsm, err := ns.refArgsToMap(args)\n\tif err != nil {\n\t\treturn \"\", err","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/urls/urls.go#L78-L114","documentation":"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.","triggerScenarios":"`{{ 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.","commonSituations":"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.","solutions":["Pass a real Page as the first argument: `{{ ref page \"about.md\" }}` (Hugo's global `page`) or `{{ ref .Page \"about.md\" }}` in shortcodes.","In partials receiving a dict context, include the page: `{{ partial \"x\" (dict \"page\" .) }}` then `{{ ref .page \"target\" }}`.","Check argument order — the Page comes first, then the ref target."],"exampleFix":"{{/* before, in a shortcode */}}\n{{ ref . \"about.md\" }}\n{{/* after */}}\n{{ ref .Page \"about.md\" }}","handlingStrategy":"type-guard","validationCode":"{{/* ref must be called with a Page as context */}}\n{{ with .Page }}{{ ref . \"/blog/post\" }}{{ end }}","typeGuard":"{{/* narrow to a real Page before calling ref */}}\n{{ if reflect.IsMap . | not }}{{ with .Page }}{{ $url := ref . \"/docs/intro\" }}{{ end }}{{ end }}","tryCatchPattern":"{{ with try (ref $page \"/docs/intro\") }}\n  {{ with .Err }}{{ warnf \"ref failed: %s\" . }}{{ end }}\n{{ end }}","preventionTips":["Pass the current Page (usually . or $.Page) as ref's first argument — inside range loops or partials the dot is often not a Page","In shortcodes use {{ ref .Page \"target\" }}, and in partials pass the page explicitly via the partial's context","Prefer the relref/ref shortcodes in content, which wire the Page automatically"],"tags":["hugo","templates","ref","page-context"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}