labstack/echo · error

missing LogValuesFunc callback function for request logger m

Error message

missing LogValuesFunc callback function for request logger middleware

What it means

Returned by RequestLoggerConfig.ToMiddleware when config.LogValuesFunc is nil. This callback is the whole point of RequestLogger — it receives the extracted RequestLoggerValues so you can emit them to your logger (slog, zap, zerolog, etc.). Without it there is nowhere to send the captured data. The parameterless RequestLogger() provides a default callback, so only WithConfig without the field triggers this.

Source

Thrown at middleware/request_logger.go:256

	mw, err := config.ToMiddleware()
	if err != nil {
		panic(err)
	}
	return mw
}

// ToMiddleware converts RequestLoggerConfig into middleware or returns an error for invalid configuration.
func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
	if config.Skipper == nil {
		config.Skipper = DefaultSkipper
	}
	now := time.Now
	if config.timeNow != nil {
		now = config.timeNow
	}

	if config.LogValuesFunc == nil {
		return nil, errors.New("missing LogValuesFunc callback function for request logger middleware")
	}

	logHeaders := len(config.LogHeaders) > 0
	headers := append([]string(nil), config.LogHeaders...)
	for i, v := range headers {
		headers[i] = http.CanonicalHeaderKey(v)
	}

	logQueryParams := len(config.LogQueryParams) > 0
	logFormValues := len(config.LogFormValues) > 0

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()

View on GitHub (pinned to 05489dc173)

Solutions

  1. Set LogValuesFunc to a function that writes v to your logger (see the package-level examples for slog/zap/zerolog/logrus).
  2. If you just want default logging via echo.Context.Logger(), use the parameterless RequestLogger() which wires a default callback.
  3. Use config.ToMiddleware() to receive the error instead of panicking.

Example fix

// before
m := middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
    LogStatus: true,
    LogURI:    true,
})
// after
m := middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
    LogStatus: true,
    LogURI:    true,
    LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error {
        c.Logger().Info("request", "uri", v.URI, "status", v.Status)
        return nil
    },
})
Defensive patterns

Strategy: validation

Validate before calling

func requestLoggerMiddleware(logValues func(*echo.Context, middleware.RequestLoggerValues) error) (echo.MiddlewareFunc, error) {
    cfg := middleware.RequestLoggerConfig{LogStatus: true, LogURI: true, LogValuesFunc: logValues}
    if cfg.LogValuesFunc == nil {
        return nil, errors.New("RequestLogger requires LogValuesFunc")
    }
    return cfg.ToMiddleware()
}

Prevention

When it happens

Trigger: Calling RequestLoggerWithConfig(RequestLoggerConfig{LogStatus: true, LogURI: true}) without setting LogValuesFunc.

Common situations: Developer enables Log* flags but forgets the callback; or assumes the middleware logs to stdout by default like the legacy Logger middleware (it does not — you must supply LogValuesFunc or use RequestLogger()).

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/fbdc0a38456afbdb.json. Report an issue: GitHub.