I’ve spent many hours trying to trace template and front matter errors from messages with less info than this one. This is a general source of pain. See also #2609, #3171, #4041, #3957, #3514, #1736, #947, #2295 and many others. It’s far more painful for people who are not intimate with the Hugo code or nuances in its behavior, so pros reading this keep in mind you probably don’t feel the pain much.
During those many hours above I’ve inserted some ad-hoc error message details in my dev fork, and I remember coming across this (and @bep’s comment within it):
In my dev fork I’ve changed line 1774 to add context (d, the thing being rendered) and also a stack trace because the message returned from recover() had little useful info:
helpers.DistinctErrorLog.Printf("Failed to render %q for %v: %s\n %s", templName, d, r, debug.Stack())
But rather than adding more ad-hoc details to error messages throughout the codebase, why not introduce a richer set of Error structures, and change method signatures to use those rather than the plain built-in error. For example, a PageError that includes info about the offending page. This forces method implementations to consistently provide certain info on error (it’s too easy right now just to return a string), and it lends itself to future work on how to handle and report errors in a way most helpful to authors, template developers and hugo developers, and dynamically adjust to different contexts (hugo vs hugo server vs testMode) as your TODO above I think is getting at.
Since @bep asked in the issue that triggered this, the reason for changing method signatures by adding more finely typed return error values is for the advantages of strongly typed methods, including return values. It allows callers to make assumptions about what’s returned, and it forced the method implementation, even as it evolves, to not get lazy about reporting errors.
Sure, but usually in other strongly typed languages resorting to such mechanisms rather than the static type system unnecessarily undermines the languages strengths. But I’m a Go newb. Is this common or idiomatic Go practice?
If you add, say, 3 new error types and the main motivation is to improve logging, changing the signature in 40 methods does not sound right, when only one “logThis” method really care about the types – and have to do a type switch anyhow.