labstack/echo · error · AddRouteError

adding duplicate route (same method+path) is not allowed

Error message

adding duplicate route (same method+path) is not allowed

What it means

Returned by DefaultRouter.Add (router.go:526-531) when a route with the same Method and Path is already registered and overwriting is disabled. The check is a linear scan of r.routes for an exact Method+Path match; AllowOverwritingRoute on the router (or allowOverwrite on the Route) bypasses it.

Source

Thrown at router.go:529

	if route.Handler == nil {
		switch route.Method {
		case RouteNotFound:
			route.Handler = r.notFoundHandler
		case http.MethodOptions:
			route.Handler = r.optionsMethodHandler
		default:
			return RouteInfo{}, newAddRouteError(route, errors.New("adding route without handler function"))
		}
	}

	method := route.Method
	path := normalizePathSlash(route.Path)

	h := applyMiddleware(route.Handler, route.Middlewares...)
	if !allowOverwritingRoute {
		for _, rr := range r.routes {
			if route.Method == rr.Method && route.Path == rr.Path {
				return RouteInfo{}, newAddRouteError(route, errors.New("adding duplicate route (same method+path) is not allowed"))
			}
		}
	}
	var headH HandlerFunc
	if r.autoHandleHEAD && method == http.MethodGet {
		headH = wrapHeadHandler(h)
	}

	paramNames := make([]string, 0)
	originalPath := path
	wasAdded := false
	var ri RouteInfo
	for i, lcpIndex := 0, len(path); i < lcpIndex; i++ {
		if path[i] == paramLabel {
			if i > 0 && path[i-1] == '\\' {
				path = path[:i-1] + path[i:]
				i--
				lcpIndex--

View on GitHub (pinned to 05489dc173)

Solutions

  1. Set RouterConfig.AllowOverwritingRoute = true (or per-route allowOverwrite) if the replacement is intentional
  2. Remove the prior route with e.Router().Remove before re-adding
  3. Dedupe registration loops and audit group prefix composition

Example fix

// before
e.GET("/users", h1)
_, err := e.GET("/users", h2) // error
// after
router := echo.NewRouter(echo.RouterConfig{AllowOverwritingRoute: true})
// or, on an existing router:
e.Router().(*echo.DefaultRouter).AllowOverwritingRoute = true
e.GET("/users", h2)
Defensive patterns

Strategy: validation

Validate before calling

for _, r := range e.Routes() {
    if r.Method == route.Method && r.Path == route.Path {
        _ = e.Router().Remove(route.Method, route.Path)
        break
    }
}
_, err := e.Router().Add(route)

Prevention

When it happens

Trigger: Registering e.GET("/users", h) twice; two route groups whose prefixes concatenate to the same final path; re-registration loops; reloading routes without enabling AllowOverwritingRoute.

Common situations: Hot-reload/plugin systems, generated routers, group prefix collisions (group "/api" + route "/api/users"), loops that register twice.

Related errors


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