Adding warnings when layoutless content exists

I was making a new site just now and I accidentally put index.html into the root of the site alongside config.yaml instead of in layout/. Naturally, when I visited http://localhost:1313, I got a blank page. However, I couldn’t figure out why. (p *PageOutput) Render() seems to be about the place where one could catch these anomalies and log a warning, so I decided to back up a bit and log a warning if there aren’t any layouts:

diff --git a/hugolib/page_output.go b/hugolib/page_output.go
index 6ea466b4..a803ebe0 100644
--- a/hugolib/page_output.go
+++ b/hugolib/page_output.go
@@ -92,10 +92,15 @@ func (p *PageOutput) copy() (*PageOutput, error) {
 }

 func (p *PageOutput) layouts(layouts ...string) ([]string, error) {
+       helpers.DistinctWarnLog.Println("blah blah blah")
        if len(layouts) == 0 && p.selfLayout != "" {
                return []string{p.selfLayout}, nil
        }

+       if len(layouts) == 0 {
+               helpers.DistinctWarnLog.Printf("in .layouts: Couldn't find a layout for page %q", p.pathOrTitle())
+       }
+
        layoutOverride := ""
        if len(layouts) > 0 {
                layoutOverride = layouts[0]
diff --git a/vendor/vendor.json b/vendor/vendor.json

This printed nothing extra when I moved index.html back out to the wrong place and ran hugo serve -w --log. I also didn’t see “blah blah blah” in log.txt after running hugo serve -w --logFile log.txt.

Am I going about this the wrong way?

Obviously; I wouldn’t assume that a method with the name Render would be responsible just because of its name. Look for a method with the name renderPages.

Quoth bep, on the pull request:

I’m pretty sure we log this as warnings today

Nope, not really. There’s an unhelpful warning for “page” and another unhelpful warning for 404.html (see below).

What I observed was that none of the code was actually checking to see if any of the filenames specified actually exist. It appears that Go’s own html/template will happily accept a list of templates and return them from (t *Template) Lookup(name string), but won’t actually verify that the templates exist before you try to execute a template and get back an empty string. This “empty string with no visible message” is what I’m trying to fix.

I’d figure that I’m seeing the log below because nothing in Hugo is ensuring that at least one template exists for each page. I figure that [en] Unable to locate layout for "404": [404.html] is showing up because something isn’t even specifying a (one-item?) list of layouts for it. Ideally, Hugo wouldn’t pester me for a layout for 404.html unless I’ve added a 404.md somewhere, but this patch isn’t the place for that.

Should I be going about this a different way?

$ ~/Projects/Go/src/github.com/gohugoio/hugo/hugo -v
INFO 2017/06/15 02:09:47 Using config file: 
INFO 2017/06/15 02:09:47 /Users/comatoast/Sites/warnme/static/ is the only static directory available to sync from
INFO 2017/06/15 02:09:47 syncing static files to /Users/comatoast/Sites/warnme/public/
WARN 2017/06/15 02:09:47 No translation bundle found for default language "en"
WARN 2017/06/15 02:09:47 Translation func for language en not found, use default.
WARN 2017/06/15 02:09:47 i18n not initialized, check that you have language file (in i18n) that matches the site language or the default language.
Started building sites ...
INFO 2017/06/15 02:09:47 found taxonomies: map[string]string{}
No layout for "/about/" found in the usual places.
Found a layout for "/"
WARN 2017/06/15 02:09:47 [en] Unable to locate layout for "page": [page/single.html.html page/single.html _default/single.html.html _default/single.html theme/page/single.html.html theme/page/single.html theme/_default/single.html.html theme/_default/single.html]
WARN 2017/06/15 02:09:47 [en] Unable to locate layout for "404": [404.html]
Found a layout for "/"
Built site for language en:
0 draft content
0 future content
0 expired content
1 regular pages created
2 other pages created
0 non-page files copied
0 paginator pages created
total in 1 ms

I’m still not sure I follow:

WARN 2017/06/15 02:09:47 [en] Unable to locate layout for "page": [page/single.html.html page/single.html _default/single.html.html _default/single.html theme/page/single.html.html theme/page/single.html theme/_default/single.html.html theme/_default/single.html]
WARN 2017/06/15 02:09:47 [en] Unable to locate layout for "404": [404.html]

The above loks fine to me. We don’t print the page name because we would in this case spam the log if you had, say, logged the page name/path.

[en] Unable to locate layout for "page": [page/single.html.html page/single.html _default/single.html.html …] didn’t help me understand what I did wrong since I don’t have any page.md or page/index.md files anywhere. I think I was misled because It’s a generic error message that looks like it’s a specific error message. If I wanted to convey this level of generality, I’d have something like

[en] Some page in content does not have a corresponding layout

Phrased like this, the generality and unhelpfulness is manifest: imagine a compiler that only prints error messages like this, without column or even line numbers:

main.cpp: syntax error

I’d like to help hugo to be more helpful than that.

I share your concern about log spam. One line per Markdown file without a layout might cause a lot of stuff to be printed, but the most common case would be when the user puts in a new .md file someplace and hasn’t gotten around to creating a layout file for it (or moving a layout file from someplace specific to someplace generic). I’d only expect large amounts of log spam if someone copies a directory full of Markdown files into content/, possibly as a way to import blog posts from Jekyll. In that case, the user would see a bunch of “missing layout for page” FEEDBACK-level warnings, but seeing the large number of messages would help him figure out what he needs to do to make a layout file in the proper place.

On websites past I’ve burned hours trying to understand why hugo is generating blank pages; an error message specific to the blank page I was seeing would have saved me loads of time. I’m trying to save others’ time, and I think clearer error messages go a long way towards that goal.

What should I do next to get better error messages? I’d like to save others the hassle of having to post their sites on discuss.gohugo.io, and you the hassle of having to answer a class of “why does this page not build?” questions.

This isn’t a syntax error with one given file, this is a broken site, and the current error message is a compromise. It could maybe be made more specific, but not if the means spamming the log with warning messages, and also not if that means adding a lot of code to Hugo.

Believe me when I say that if you have a site with thousands of pages, having Hugo print thousands of messages on every build isn’t helpful.