labstack/echo · critical

panic: err from g.AddRoute in Group.Add

Error message

panic: err from g.AddRoute in Group.Add

What it means

Panicked inside Group.Add (group.go:198) when g.AddRoute returns an error for the single route being added. Group.Add wraps one method+path+handler registration and panics on any router error (invalid path, conflicting params, duplicate route). This is the v4 convention; v5 returns the error.

Source

Thrown at group.go:198

}

// RouteNotFound implements `Echo#RouteNotFound()` for sub-routes within the Group.
//
// Example: `g.RouteNotFound("/*", func(c *echo.Context) error { return c.NoContent(http.StatusNotFound) })`
func (g *Group) RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo {
	return g.Add(RouteNotFound, path, h, m...)
}

// Add implements `Echo#Add()` for sub-routes within the Group. Panics on error.
func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) RouteInfo {
	ri, err := g.AddRoute(Route{
		Method:      method,
		Path:        path,
		Handler:     handler,
		Middlewares: middleware,
	})
	if err != nil {
		panic(err) // this is how `v4` handles errors. `v5` has methods to have panic-free usage
	}
	return ri
}

// AddRoute registers a new Routable with Router
func (g *Group) AddRoute(route Route) (RouteInfo, error) {
	// Combine middleware into a new slice to avoid accidentally passing the same slice for
	// multiple routes, which would lead to later add() calls overwriting the
	// middleware from earlier calls.
	groupRoute := route.WithPrefix(g.prefix, append([]MiddlewareFunc{}, g.middleware...))
	return g.echo.add(groupRoute)
}

View on GitHub (pinned to 05489dc173)

Solutions

  1. Read the wrapped error from AddRoute to find the exact router rejection reason.
  2. Remove duplicate registrations for the same method+path.
  3. Keep parameter names consistent at each path segment across all routes.
  4. Use echo.Config{...} or distinct prefixes to avoid cross-group collisions.

Example fix

// before
g.GET("/users/:id", h1)
g.GET("/users/:id", h2) // duplicate -> panic
// after
g.GET("/users/:id", h1)
g.GET("/users/:id/edit", h2)
Defensive patterns

Strategy: validation

Validate before calling

// Wrap a single Add in a recover to convert the panic into an error for diagnostics.
func addSafe(g *echo.Group, method, path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("Group.Add %s %s: %v", method, path, r)
        }
    }()
    g.Add(method, path, h, m...)
    return nil
}

Prevention

When it happens

Trigger: Calling g.Add(method, path, handler) (or convenience methods g.GET, g.POST, etc.) with a path the router rejects: invalid parameter syntax, conflicting wildcard/param at the same position, or a duplicate route registration.

Common situations: Duplicate route registration; mixing ':param' and '*wildcard' at the same path segment; invalid characters in the path; registering the same method+path twice across groups.

Related errors


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