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
- Read the wrapped error after 'build: router:' — it names the exact conflicting route.
- Search your route registrations for duplicates: same HTTP method + path registered more than once.
- Ensure wildcard/path parameters appear only as the final segment (e.g. /files/{p:path}, not /files/{p:path}/more).
- Ensure each path segment contains at most one dynamic parameter (no /files/{name}-{ext}).
- 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
- Keep a single source of truth for route registration to avoid duplicates.
- Never place {param:path} anywhere but the last segment.
- Never mix dynamic params with static text in one segment.
- Write a startup test that builds the app in CI.
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
- build: %w
- build: view engine: %v
- build: inject live reload: failed: %v
- failed to connect to the server after %d retries
- ErrEmptyFormField
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/6f27325ba7a8a5d8.
Report an issue: GitHub.