CIRCUIT BREAKER FIX
Comprehensive documentation system guides
🔥 Circuit Breaker Fix - Select Project Route
Problem
Application was attempting to load documentation files for the /select-project route:
- Tried to fetch
/docs/select-project.md - Tried to fetch
/docs/select-project.mdc - Circuit breaker activated after multiple failed attempts
/select-projectis a UI component route, not a documentation page
Root Cause
Multiple services were trying to load documentation content for routes that should be handled by UI components:
- NavigationService - Tried to load navigation structure
- MarkdownService - Tried to load markdown content
- DynamicPageComponent - Tried to resolve doc paths
Solution - Defense in Depth (3 Layers)
✅ Layer 1: Route Configuration
File: apps/docs-angular/src/app/app.routes.ts
Ensured special routes are defined BEFORE catch-all routes:
export const routes: Routes = [
// 🎯 MUST BE FIRST - Before any catch-all routes!
{ path: 'select-project', loadComponent: ProjectSelectionComponent },
{ path: 'admin', loadComponent: ... },
// Root redirects
{ path: '', redirectTo: '/select-project', pathMatch: 'full' },
{ path: 'es', redirectTo: '/select-project', pathMatch: 'full' },
// Documentation routes with guards
{ path: ':section/:page', loadComponent: DynamicPageComponent, canActivate: [projectSelectedGuard] },
{ path: ':section/:subsection/:page', loadComponent: DynamicPageComponent, canActivate: [projectSelectedGuard] },
// Catch-all LAST!
{ path: '**', loadComponent: DynamicPageComponent, canActivate: [projectSelectedGuard] }
];
✅ Layer 2: NavigationService Guard
File: apps/docs-angular/src/app/services/navigation.service.ts (Lines 128-135)
Skip structure loading for UI routes:
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) => {
const decodedUrl = decodeURIComponent(event.url);
// 🎯 SKIP: Don't process special UI routes
if (decodedUrl === '/select-project' ||
decodedUrl.startsWith('/select-project?') ||
decodedUrl.startsWith('/admin')) {
console.log('⏭️ Skipping structure load for UI route:', decodedUrl);
this.currentPath.set(decodedUrl);
return; // EXIT EARLY
}
// ... rest of navigation logic
});
✅ Layer 3: MarkdownService Guard
File: apps/docs-angular/src/app/services/markdown.service.ts (Lines 302-308)
Skip content loading for UI routes:
loadContent(path: string, language: 'en' | 'es' = 'en'): Observable<MarkdownContent> {
const cleanPath = path.startsWith('/') ? path.slice(1) : path;
// 🎯 SKIP: Don't try to load docs for special UI routes
if (cleanPath === 'select-project' ||
cleanPath.startsWith('select-project?') ||
cleanPath.startsWith('admin')) {
console.log('⏭️ Skipping doc load for UI route:', cleanPath);
return of(this.createFallbackContent('', language));
}
// ... rest of content loading logic
}
✅ Layer 4: DynamicPageComponent Guard
File: apps/docs-angular/src/app/pages/dynamic-page/dynamic-page.component.ts (Lines 49-55)
Skip path updates for UI routes:
private updatePathFromRoute(): void {
const pathSegments = this.route.snapshot.url.map(segment => segment.path);
const fullPath = '/' + pathSegments.join('/');
// 🎯 SKIP: Don't try to load docs for special UI routes
if (fullPath === '/select-project' ||
fullPath.startsWith('/select-project?') ||
fullPath.startsWith('/admin')) {
console.log('⏭️ DynamicPageComponent: Skipping UI route:', fullPath);
return; // EXIT EARLY
}
// ... rest of path resolution logic
}
Circuit Breaker Behavior
Before Fix:
🚨 EMERGENCY CIRCUIT BREAKER: Blocking /docs/select-project.md (circuit broken for 59s)
🚨 EMERGENCY CIRCUIT BREAKER: Blocking /docs/select-project.mdc (circuit broken for 59s)
[Repeated attempts to load non-existent files]
After Fix:
⏭️ Skipping structure load for UI route: /select-project
⏭️ Skipping doc load for UI route: select-project
⏭️ DynamicPageComponent: Skipping UI route: /select-project
[No file loading attempts - clean execution]
Circuit Breaker Reset
The circuit breaker will automatically reset after:
- 60 seconds for timed-out requests
- Manual reset via
clearFileExistsCache()method
Old requests in the breaker cache will expire naturally.
Testing Checklist
- Build succeeds without errors
- Routes defined in correct order
- Guards in place at all layers
- Test navigation to
/select-project(should load cleanly) - Test navigation to project-specific docs (should work normally)
- Verify no circuit breaker errors in console
- Verify no failed network requests for UI routes
Benefits
- Performance: No unnecessary file requests for UI routes
- Clean Logs: No circuit breaker errors cluttering console
- Defense in Depth: Multiple layers prevent the issue at different levels
- Maintainability: Clear, documented guards that explain intent
- Extensibility: Easy to add more UI routes to the guard list
Future UI Routes
To add more UI-only routes (no doc loading):
- Add route definition BEFORE catch-all in
app.routes.ts - Add path check to NavigationService guard
- Add path check to MarkdownService guard
- Add path check to DynamicPageComponent guard
Related Files
apps/docs-angular/src/app/app.routes.tsapps/docs-angular/src/app/services/navigation.service.tsapps/docs-angular/src/app/services/markdown.service.tsapps/docs-angular/src/app/pages/dynamic-page/dynamic-page.component.ts
Status: ✅ FIXED
Build: ✅ SUCCESS
Date: October 28, 2025
Impact: Critical issue resolved - Project selection page now loads cleanly