kataras/iris · error

build: router: %w

Error message

build: router: %w

What it means

Iris wraps errors from Router.BuildRouter during app build as 'build: router: %w'. BuildRouter compiles the APIBuilder's registered routes into the radix/trie router; failures almost always come from invalid route registrations — duplicate paths, invalid parameter types, or conflicting wildcards.

Source

Thrown at iris.go:767

		if _, err := injectLiveReload(app); err != nil {
			return fmt.Errorf("build: inject live reload: failed: %v", err)
		}

		if app.config.ForceLowercaseRouting {
			// This should always be executed first.
			app.Router.PrependRouterWrapper(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
				r.Host = strings.ToLower(r.Host)
				r.URL.Host = strings.ToLower(r.URL.Host)
				r.URL.Path = strings.ToLower(r.URL.Path)
				next(w, r)
			})
		}

		// create the request handler, the default routing handler
		routerHandler := router.NewDefaultHandler(app.config, app.logger)
		err := app.Router.BuildRouter(app.ContextPool, routerHandler, app.APIBuilder, false)
		if err != nil {
			return fmt.Errorf("build: router: %w", err)
		}
		app.HTTPErrorHandler = routerHandler

		if app.config.Timeout > 0 {
			app.Router.SetTimeoutHandler(app.config.Timeout, app.config.TimeoutMessage)

			app.ConfigureHost(func(su *Supervisor) {
				if su.Server.ReadHeaderTimeout == 0 {
					su.Server.ReadHeaderTimeout = app.config.Timeout + 5*time.Second
				}

				if su.Server.ReadTimeout == 0 {
					su.Server.ReadTimeout = app.config.Timeout + 10*time.Second
				}

				if su.Server.WriteTimeout == 0 {
					su.Server.WriteTimeout = app.config.Timeout + 15*time.Second
				}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Read the wrapped error after 'build: router:' — it names the exact conflicting route.
  2. Search your route registrations for duplicates: same HTTP method + path registered more than once.
  3. Ensure wildcard/path parameters appear only as the final segment (e.g. /files/{p:path}, not /files/{p:path}/more).
  4. Ensure each path segment contains at most one dynamic parameter (no /files/{name}-{ext}).
  5. Log every registered route before Run() and diff for unintended duplicates.

Example fix

// before (duplicate + mid-path wildcard)
app.Get("/users/{id}", getUser)
app.Get("/users/{id}", getUserV2)
app.Get("/files/{p:path}/raw", raw)
// after
app.Get("/users/{id}", getUser) // single registration
app.Get("/files/{p:path}", raw)
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]string{}
for _, r := range routes {
    key := r.Method + " " + normalize(r.Path)
    if prev, dup := seen[key]; dup {
        log.Fatalf("duplicate route %s (also %s)", key, prev)
    }
    seen[key] = key
    if strings.Count(seg, "{") > 1 || hasWildcardMidPath(r.Path) {
        log.Fatalf("invalid route path %s", r.Path)
    }
}

Type guard

func hasWildcardMidPath(p string) bool {
    parts := strings.Split(strings.Trim(p, "/"), "/")
    for i, s := range parts {
        if strings.HasSuffix(s, ":path}") && i < len(parts)-1 {
            return true
        }
    }
    return false
}

Try / catch

if err := app.Run(iris.Addr(":8080")); err != nil {
    if strings.Contains(err.Error(), "build: router:") {
        log.Fatalf("route registration problem: %v", err)
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: Registering two identical routes on the same method/path; using %v invalid macro expressions like /{param:int:min=1:min=2}; wildcard params ({param:path}) not at the end of the path; conflicting static vs wildcard segments on the same subtree; calling Build via New/Run after such registrations.

Common situations: Auto-generating routes in a loop that registers the same handler path twice; refactoring a path from /users/{id} to /users/{id:path} while keeping /users/all; upgrading Iris where stricter trie validation rejects paths previously tolerated (see #2024-style checks).

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/6f27325ba7a8a5d8. Report an issue: GitHub.