go: text/template: wrap errors returned by custom template functions
What version of Go are you using (go version
)?
go version go1.13 windows/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
set GO111MODULE=on set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\User\AppData\Local\go-build set GOENV=C:\Users\User\AppData\Roaming\go\env set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GONOPROXY= set GONOSUMDB= set GOOS=windows set GOPATH=D:\Go set GOPRIVATE= set GOPROXY=direct set GOROOT=C:\Go\go1.13 set GOSUMDB=sum.golang.org set GOTMPDIR= set GOTOOLDIR=C:\Go\go1.13\pkg\tool\windows_amd64 set GCCGO=gccgo set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD=E:\Projects\test\go.mod set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\User\AppData\Local\Temp\go-build112356450=/tmp/go-build -gno-record-gcc-switches
What did you do?
I’m trying to get the error returned by my custom template function. The error is a struct implementing the error
interface.
Execute
returns template.ExecError
and despite the fact that it implements Unwrap() error
, calling Unwrap
returns *errors.errorsString
, not my error implementation.
Thus, there is no way to get the original error.
Code:
package main
import (
"errors"
"fmt"
"os"
"text/template"
)
type MyError struct {
Value int
}
func (e *MyError) Error() string { return "error message" }
func test(val int) (string, error) {
return "", &MyError{
Value: val,
}
}
func main() {
t := template.Must(template.New("test").Funcs(template.FuncMap{
"test": test,
}).Parse("{{ test 10 }}"))
err := t.Execute(os.Stdout, nil)
if err != nil {
var e *MyError
fmt.Println(errors.As(err, &e)) // <-- false
}
}
What did you expect to see?
true
What did you see instead?
false
Additional notes
- Documentation for
template.FuncMap
states that:
if the second (error) return value evaluates to non-nil during execution, execution terminates and Execute returns that error
-
The same applies for method calls like
{{ .Object.Method }}
. -
Both
text/template
andhtml/template
are affected.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 4
- Comments: 16 (8 by maintainers)
Commits related to this issue
- templates: Add fileExists and httpError template actions The httpError function isn't particularly useful until https://github.com/golang/go/issues/34201 is fixed in the Go standard lib. — committed to caddyserver/caddy by mholt 3 years ago
- Keep up (#3) * cmd/compile: graceful handle error in noder LoadPackage When syntax.Parse returns error, noder.file will be nil. Currently, we continue accessing it regardlessly and depend on gc.h... — committed to gopher-lang/gopher by auxten 3 years ago
- templates: Propagate httpError to HTTP response Now possible with Go 1.17. See https://github.com/golang/go/issues/34201. — committed to caddyserver/caddy by mholt 3 years ago
I’ll add some tests right away so that it’s ready for 1.17
Maybe you’re right, I’m not sure. My instinct is that this kind of internal change, even if it’s definitely correct, could very easily change the behavior of existing programs. So my default response is that three weeks before the final release is too late, given that there’s nearly no time to get it tested.
Then again, rc1 is late so that could still work as a way to get it tested. Normally it would already be out by now.
Sending a new CL to advance the change sounds like the right way. At minimum, the original change needs a test, like Ian said.