Bugfix: NestJS ThemesController route ordering: PUT /themes/active w...
Documentation for Sessions
🐛 Bugfix: NestJS ThemesController route ordering: PUT /themes/active w...
Date: 2026-02-25
Time: 20:18:37 UTC
Session: gspace1-141.10
Agent: backend
Confidence: 97%
Status: ✅ Documented
📋 Decision Context
Question:
NestJS ThemesController route ordering: PUT /themes/active was shadowed by PUT /themes/:themeId — how should routes be ordered?
Task: Fix NestJS route ordering for theme active endpoint
🎯 Decision Made
Chosen:
Move @Put('active') before @Put(':themeId') in the controller class
Options Considered:
- Move @Put('active') before @Put(':themeId') in the controller class
- Use a dedicated /themes-settings/active endpoint to avoid parametric collision
- Add a regex constraint to :themeId to exclude 'active'
- Keep current order and use middleware to reroute
💭 Reasoning
ROOT CAUSE: NestJS matches routes in DECLARATION ORDER within a controller class. @Put(':themeId') was declared at line 172, @Put('active') at line 181. When the frontend called PUT /themes/active with body { themeId: 'theme-default-dark' }, NestJS matched :themeId first, binding themeId='active'. This called upsertTheme({ id: 'active' }) which created a bogus document with _id='active' in the themes collection instead of setting the active theme ID in theme_settings. The fix reorders so static routes (@Put('active'), @Delete()) are declared BEFORE parametric routes (@Put(':themeId'), @Delete(':themeId')). Same principle applied to DELETE routes. WHY SIMPLEST FIX IS BEST: NestJS documentation explicitly states that specific routes must precede parametric routes. Adding regex constraints or separate endpoints adds unnecessary complexity. This is a well-known NestJS convention. WHAT WOULD MAKE THIS WRONG: Only if NestJS changed its routing algorithm to match specificity over declaration order (unlikely, as Express/Fastify routers are order-based). EARLY WARNING: Any NestJS controller with both @Method('static-path') and @Method(':param') at the same depth is a candidate for this bug.
📁 Files Involved
apis/backend-api/src/app/themes/themes.controller.ts
🔗 Related
- Decision ID:
dev_1772050717035_t57ezfe - Session: 141
- Workspace: gspace1
Auto-generated by MCP Smart Consolidation