tpl: Improve the Execute panic error message
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 17 Oct 2018 06:24:45 +0000 (08:24 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 17 Oct 2018 06:25:57 +0000 (08:25 +0200)
See #5327

hugolib/hugo_sites_build_errors_test.go
tpl/template.go

index 0742207582187088ca84fa3e46f4fe97da75751a..cf347a2d15c04d212fd966a51862355358f94bef 100644 (file)
@@ -109,6 +109,18 @@ func TestSiteBuildErrors(t *testing.T) {
                                        a.assertLineNumber(2, err)
                                },
                        },*/
+
+               {
+                       name:     "Panic in template Execute",
+                       fileType: single,
+                       fileFixer: func(content string) string {
+                               return strings.Replace(content, ".Title", ".Parent.Parent.Parent", 1)
+                       },
+                       assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
+                               assert.Error(err)
+                               assert.Contains(err.Error(), "layouts/_default/single.html")
+                       },
+               },
        }
 
        for _, test := range tests {
index 02b2d4a9b3b3bcf53816b07ba3d5e40971832cd1..68673a1fc91ca04ac8f4894bea7467cd52fd2681 100644 (file)
@@ -115,8 +115,9 @@ func extractBaseOf(err string) string {
 func (t *TemplateAdapter) Execute(w io.Writer, data interface{}) (execErr error) {
        defer func() {
                // Panics in templates are a little bit too common (nil pointers etc.)
+               // See https://github.com/gohugoio/hugo/issues/5327
                if r := recover(); r != nil {
-                       execErr = t.addFileContext(t.Name(), fmt.Errorf("panic in Execute: %s", r))
+                       execErr = t.addFileContext(t.Name(), fmt.Errorf(`panic in Execute: %s. See "https://github.com/gohugoio/hugo/issues/5327" for the reason why we cannot provide a better error message for this.`, r))
                }
        }()
 
@@ -152,7 +153,7 @@ func (t *TemplateAdapter) addFileContext(name string, inerr error) error {
 
        master, hasMaster := t.NameBaseTemplateName[name]
 
-       ferr := errors.Wrapf(inerr, "execute of template %q failed", realFilename)
+       ferr1 := errors.Wrapf(inerr, "execute of template %q failed", realFilename)
 
        // Since this can be a composite of multiple template files (single.html + baseof.html etc.)
        // we potentially need to look in both -- and cannot rely on line number alone.
@@ -175,7 +176,7 @@ func (t *TemplateAdapter) addFileContext(name string, inerr error) error {
        }
 
        // TODO(bep) 2errors text vs HTML
-       fe, ok := herrors.WithFileContext(ferr, f, "go-html-template", lineMatcher)
+       fe, ok := herrors.WithFileContext(ferr1, f, "go-html-template", lineMatcher)
        if ok || !hasMaster {
                return fe
        }
@@ -187,8 +188,14 @@ func (t *TemplateAdapter) addFileContext(name string, inerr error) error {
        }
        defer f.Close()
 
-       ferr = errors.Wrapf(inerr, "execute of template %q failed", realFilename)
-       fe, _ = herrors.WithFileContext(ferr, f, "go-html-template", lineMatcher)
+       ferr2 := errors.Wrapf(inerr, "execute of template %q failed", realFilename)
+       fe, ok = herrors.WithFileContext(ferr2, f, "go-html-template", lineMatcher)
+
+       if !ok {
+               // Return the most specific.
+               return ferr1
+
+       }
        return fe
 
 }