gohugoio/hugo · error

%v

Error message

%v

What it means

Raised by `safeCall` when the invoked function panics (funcs.go:356-364). The panic value is recovered and returned as a template-execution error formatted with `%v`. This surfaces arbitrary panics from user-supplied FuncMap entries or builtins as template errors rather than crashing the process.

Source

Thrown at tpl/internal/go_templates/texttemplate/funcs.go:362

		}

		var err error
		if argv[i], err = prepareArg(arg, argType); err != nil {
			return reflect.Value{}, fmt.Errorf("arg %d: %w", i, err)
		}
	}
	return safeCall(fn, argv)
}

// safeCall runs fun.Call(args), and returns the resulting value and error, if
// any. If the call panics, the panic value is returned as an error.
func safeCall(fun reflect.Value, args []reflect.Value) (val reflect.Value, err error) {
	defer func() {
		if r := recover(); r != nil {
			if e, ok := r.(error); ok {
				err = e
			} else {
				err = fmt.Errorf("%v", r)
			}
		}
	}()
	ret := fun.Call(args)
	if len(ret) == 2 && !ret[1].IsNil() {
		return ret[0], ret[1].Interface().(error)
	}
	return ret[0], nil
}

// Boolean logic.

func truth(arg reflect.Value) bool {
	t, _ := isTrue(indirectInterface(arg))
	return t
}

// and computes the Boolean AND of its arguments, returning

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Reproduce the call in Go and fix the panic at its source (the function body).
  2. Add nil/error checks in the func and return a proper `error` (the (value, error) return convention) instead of panicking.
  3. Validate inputs in the template before calling.
  4. Pin or upgrade the module exposing the panicking function.

Example fix

// before (Go func)
func first(s []string) string { return s[0] }   // panics on empty

// after
func first(s []string) (string, error) {
    if len(s) == 0 { return "", errors.New("empty slice") }
    return s[0], nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate inputs in-template before calling:
//   {{if .S}}{{call .First .S}}{{end}}
// Better: fix the func to return (value, error) and check inputs.

Try / catch

// safeCall already recovers panics into errors; surface them:
// In Go rendering code:
err := tmpl.Execute(w, data)
if err != nil {
    var pe *template.Error
    if errors.As(err, &pe) {
        log.Printf("template exec error: %v", pe)
    }
    return err
}

Prevention

When it happens

Trigger: A registered FuncMap entry that panics (nil deref, index-out-of-range, divide-by-zero, explicit `panic()`); a method called via template that performs an unsafe operation on its inputs.

Common situations: Buggy custom template functions; funcs that assume non-nil input but receive nil from templates; integer division by zero in a helper; third-party Hugo module exposing a panicking func.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/12d739bd02026e9d. Report an issue: GitHub.