Problem with new 0.65.x .GetPage relative lookups

I’m trying to test my blog with 0.65.2 (since it looks like the blackfriday code-block regression has been fixed), but I’m unable to get the new .GetPage to retrieve pages reliably.

Old code (global lookup that takes advantage of the fact that the title of an entry in the /comments section is identical to the filename of the entry in /post that it’s attached to):

{{ with $.Site.GetPage "page" (printf "%s.md" .Title) }}
  {{ partial "article-hidden" . }}
{{end}}

New code, which only works for some pages:

{{$.Scratch.Set "foo" (printf "%s.md" .Title)}}
{{ with $.Site.GetPage "/post"}}
  {{ with .GetPage ($.Scratch.Get "foo") }}
    {{ partial "article-hidden" . }}
  {{end}}
{{end}}

It successfully retrieves entries with paths like /post/006167.md, but fails on entries with paths like /post/0000/000038.md. [update: to clarify, the site builds without errors or warnings, it’s just not loading some pages at all]

It appears that the new “relative lookups” are not “in this section”, but just “in this directory”. Is that correct, and if so, what’s the recommended workaround?

-j

@jgreely

Your project is not the only one that seems affected by this change.

There are a couple of themes that also throw the ambiguous page reference error.

See: https://github.com/gohugoio/hugoThemes/issues/810

May I suggest that you open a GitHub issue.

I’m not getting ambiguous-reference errors, it’s not finding the page at all.

-j

@jgreely probably a bug. I will look into this tomorrow.

I’ve created a small site that demonstrates the problem. Under 0.64.0, both .GetPage and the standard range in the theme show both the posts/post01.md and posts/foo/post02.md entries. Under 0.65.2, .GetPage can’t find post02.md because it’s in a sub-directory.

-j

@jgreely I have looked at your case, and it matches a line in the release notes’ notes section:

.GetPage "members.md" (the Page method) will now only do relative lookups, which is what most people would expect.

So for this:

{{$.Scratch.Set "foo" (printf "%s.md" .Title)}}
{{ with $.Site.GetPage "/post"}}
  {{ with .GetPage ($.Scratch.Get "foo") }}
    {{ partial "article-hidden" . }}
  {{end}}
{{end}}

Using .Title above we would before 0.65 fall back to a lookup using the base name only (e.g. 000038).

Note that I don’t understand the “what you’re trying to do” with the above (it looks like it could be solved with a simpler construct), but this should provide a correct lookup:

{{$.Scratch.Set "foo" (printf "%s.md" .Path)}}
{{ with $.Site.GetPage "/post"}}
  {{ with .GetPage ($.Scratch.Get "foo") }}
    {{ partial "article-hidden" . }}
  {{end}}
{{end}}

@bep That wouldn’t work. The template (in this case, a taxonomy page) is loading pages from a different section, so your suggestion of .Path wouldn’t help at all. Please look at the minimal repeat-by repo I provided.

I’m organizing content in sub-directories (not nested sections!) to keep the individual directory size manageable. That is, instead of having 3,812 files in content/post/, I have ~50 sub-directories (content/post/0050/, etc), each containing ~100 files (005028.md), plus the most recent entries directly in content/post/.

Elsewhere in the site, I refer to these pages by their file name. Before 0.22 was released, I used a range…where expression based on front matter to do this lookup (e.g. post “005028” is located in content/post/0050/005028.md, and has front matter entry = "005028").

After 0.22, I was able to replace this expression with the new GetPage and reduce my build time by 20%:

{{ range where ($.Site.GetPage "section" "post").Pages "Params.entry" .Title }}

I’d rather not go back to the old way; my site’s bigger than it was in 2017.

-j

@jgreely as I said, using the .Title as lookup key does not make much sense to me. But if you want that behaviour, you need to drop the “relative lookup” (which only worked earlier because of the mentioned fallback lookup).

So:

 {{ with site.GetPage .Title)}}
    {{ partial "article-hidden" . }}
  {{end}}

Or something.

@bep I’m sorry, but your suggestion is not useful for solving the problem. I now regret posting my exact template code before creating the sample repo, because you’re focusing on the wrong thing. .Title is not part of the problem, it just happens to be the source of the string I used to identify the file name of the desired content file.

Before 0.65, .GetPage was capable of retrieving pages in a sub-directory of a section when given just the file name (content/post/0050/005028.md). Now it will only retrieve pages that are in the top-level directory of a section (content/post/005028.md).

I don’t know the full path. I only know that section “post” contains an article with file name “005028.md”. range still finds all the pages in a section, .GetPage doesn’t. Not sure how I can make this any clearer.

I don’t want to move all 3,218 files back into one directory. That sucks for file management.

-j

As I said, Hugo’s GetPage never did any “relative file searching down in sub folders”. If you have unique (base) filenames, that will work – but not from $section.GetPage (this is admittedly a change in Hugo 0.65, but looking at your code above I’m convinced it removes more confusion than it adds).

I don’t know how to make this any clearer.

I have looked at your test repo. It’s the same construct.

Okay, fine; you don’t consider “retrieving pages in a section” to be a valid use of .GetPage. If the performance hit of range…where isn’t too severe, I may be able to use new releases of Hugo. Otherwise, I’ll just stick with the last one that works sensibly. Not worth any more of my time arguing about this regression with you.

-j

I didn’t say that. I’m saying that this hasn’t conceptually changed since 0.64.

So, this:

{{$.Scratch.Set "foo" (printf "%s.md" .Title)}}
{{ with $.Site.GetPage "/post"}}
  {{ with .GetPage ($.Scratch.Get "foo") }}
    {{ partial "article-hidden" . }}
  {{end}}
{{end}}

Should be the same as:

{{$.Scratch.Set "foo" (printf "%s.md" .Title)}}
  {{ with site.GetPage ($.Scratch.Get "foo") }}
    {{ partial "article-hidden" . }}
  {{end}}
{{end}}

If you mean that is not the case, then it’s a bug and someone should look into it.

1 Like

The sample repo demonstrates quite clearly that the behavior changed between 0.64 and 0.65. Under 0.64, it finds both pages; under 0.65, it doesn’t find the one that’s in the sub-directory.

-j

@jgreely I have looked at your repo, and after adjusting it to match what I have been saying earlier in this thread, I get the expected output.

See https://github.com/jgreely/hugo-getpage-subdir-bug/pull/1

@bep On the non-toy site, that just caused Hugo to die after the first five ambiguous-reference errors, so no, it’s not a viable solution.

Since you’re not interested in fixing it, I suggest updating the docs to say that .GetPage with a file name only searches the current directory, not the current section. Describing it as “relative” is deceptive.

I’ll try reverting that template to use the pre-0.22 way of retrieving specific files, but if the performance hit is too high, I’ll just stay at 0.59.1 forever for that site.

-j

I need to understand the problem to fix it.

Let us continue this discussion at https://github.com/gohugoio/hugo/pull/6951

“Passing a file name with extension to .GetPage no longer finds content files that are not located in the top-level directory of the current section. Changing the argument to omit the ‘.md’ searches the entire site, and throws ambiguous-reference errors if it finds more than one match.”

The code that fails in my test repo is directly based on the example in the GetPage docs:

{{ with .Site.GetPage "/blog" }}
{{ with .GetPage "my-post.md" }}{{ .Title }}{{ end }}
{{ end }}

How many ways do I need to say that this does not work in 0.65.x if “my-post.md” is in content/blog/anything/my-post.md instead of content/blog/my-post.md?

Meanwhile, reverting to the pre-0.22 range…where lookup added an average of 24% to my build time, as expected. Joy.

-j