Facebook Pixel

Common Express Router Mistakes (and How to Avoid Them)

Routers have predictable failure modes. Here are common mistakes and fixes.

Common Express Router Mistakes

Express routers have predictable failure modes. Here are common mistakes and how to avoid them.

Mistake 1: Routes in Wrong Order

router.get('/:id', getUser) is declared before router.get('/me', getMe). /me matches /:id first, so me is treated as id. Fix: declare /me before /:id.

Mistake 2: Wrong Mount Path

app.use('/', usersRouter) instead of app.use('/users', usersRouter). All routes hit / instead of /users. Fix: mount with the right prefix.

Mistake 3: Router Created but Not Mounted

You create a router in routes/posts.js but forget app.use('/posts', postsRouter) in app.js. The route 404s. Fix: mount every router in app.js.

Mistake 4: Forgetting router.use(auth) on Protected Routes

You forget to apply auth. Routes are public. Fix: add router.use(auth) at the top of the router file (after any public routes).

Mistake 5: Public Routes Inside Auth Router

You put /signup and /login after router.use(auth). They require auth, which is wrong. Fix: put public routes before router.use(auth).

Mistake 6: Deep Nesting

/users/:userId/posts/:postId/comments/:commentId is too deep. Hard to maintain. Fix: use a separate top-level router with a filter (?post=postId) for deeper resources.

Mistake 7: Same Router Mounted Multiple Times

You mount usersRouter under /users and /api/v1/users. Now there are two ways to reach the same routes. Fix: pick one. If versioning, mount only the current version.

Mistake 8: Logic in Routes

You put business logic in route declarations. Fix: routes only declare endpoints and bind to controllers. Logic lives in services.

Mistake 9: No Validation on Routes

You forget to validate input. Bad data reaches the controller. Fix: apply validate(schema) per route that accepts input.

Mistake 10: Sync Handlers Without asyncHandler

You use async handlers without asyncHandler. Promise rejections are swallowed. Fix: wrap with asyncHandler so rejections go to the error handler.

The Takeaway

Common Express router mistakes: routes in wrong order (/:id before /me), wrong mount path, router not mounted, forgetting auth, public routes inside auth router, deep nesting, mounting the same router twice, logic in routes, no validation, and sync handlers without asyncHandler.

Routes in wrong order, wrong mount path, router not mounted, forgetting auth, public routes inside auth router, deep nesting, mounting the same router twice, logic in routes, no validation, and sync handlers without asyncHandler.

Because /:id was declared before /me. /:id matches any string, including 'me'. Fix: declare /me before /:id, or use a different path like /me/profile.

Either the router was not mounted in app.js (app.use('/path', router)), or the mount path is wrong. Check that you mount every router with the right prefix.

You put them after router.use(auth). Public routes must be declared before router.use(auth), or in a separate router that does not apply auth.

URLs get long and rigid (/users/:userId/posts/:postId/comments/:commentId). Hard to refactor. Use a separate top-level router with a filter (?post=postId) for deeper resources. Keeps URLs clean and flexible.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.