LOADCONTENT EXTENSION DETECTION FIX
Comprehensive documentation system guides
LoadContent Extension Detection Fix
Date: October 29, 2025
Time: 12:28 PM PST
Status: ๐ฏ CRITICAL FIX COMPLETE
Purpose: Fix MarkdownService.loadContent() to respect file extensions passed from SearchService
๐จ The Problem
Even after fixing detectFileType() to prioritize .mdc files for project routes, the circuit breaker continued triggering because loadContent() was hardcoded to use .md files.
Code Flow
- โ
SearchServicecorrectly extracts.mdcfrom manifest - โ
SearchServicepasses path WITH.mdctoloadContent() - โ
loadContent()ignores the extension and hardcodes.md - ๐จ Circuit breaker activates (11 requests trying
.mdwhen file is.mdc)
Root Cause
loadContent(path: string, language: 'en' | 'es' = 'en'): Observable<MarkdownContent> {
// ...
// ๐ DIRECT MD LOADING - Load .md files directly
const possiblePaths = this.generatePossiblePaths(cleanPath, targetLanguage, '.md'); // โ HARDCODED!
// ...
}
This completely bypassed the detectFileType() fix!
โ The Solution
Modified loadContent() to intelligently handle file extensions:
New Logic
- Check if path has extension (
.mdor.mdc) - If YES: Use the provided extension directly
- If NO: Call
detectFileType()to determine correct extension
Implementation
// ๐ฏ SMART FILE TYPE DETECTION
// Check if path already has an extension (.md or .mdc)
// If yes, use it. If no, detect the correct extension.
const hasExtension = /\.(md|mdc)$/i.test(cleanPath);
if (hasExtension) {
// Path already has extension - use it directly
const extension = cleanPath.match(/\.(md|mdc)$/i)?.[0] || '.md';
console.log(`๐ Using provided extension for: ${cleanPath}`);
const possiblePaths = this.generatePossiblePaths(cleanPath, targetLanguage, extension);
// Load content with specified extension
const contentPromise = this.tryLoadFromPaths(possiblePaths).pipe(
map(({ content, actualPath }) => {
const parsed = this.parseMarkdownContent(content, targetLanguage, actualPath);
this.contentCache.set(cacheKey, parsed);
return content;
}),
catchError(() => {
const fallback = this.createFallbackContent(cleanPath, targetLanguage);
return of(fallback.content || `# ${cleanPath}\n\nContent not available.`);
})
).toPromise();
MarkdownService.globalContentCache.set(globalContentKey, contentPromise);
MarkdownService.globalContentTimestamps.set(globalContentKey, now);
return from(contentPromise).pipe(
map(content => this.parseMarkdownContent(content, targetLanguage, cleanPath))
);
}
// No extension provided - use detectFileType to determine .md vs .mdc
console.log(`๐ No extension in path, detecting file type for: ${cleanPath}`);
return this.detectFileType(cleanPath, targetLanguage).pipe(
switchMap(fileType => {
console.log(`๐ Detected file type: ${fileType} for ${cleanPath}`);
const possiblePaths = this.generatePossiblePaths(cleanPath, targetLanguage, `.${fileType}`);
// Load content with detected extension
const contentPromise = this.tryLoadFromPaths(possiblePaths).pipe(
map(({ content, actualPath }) => {
const parsed = this.parseMarkdownContent(content, targetLanguage, actualPath);
this.contentCache.set(cacheKey, parsed);
return content;
}),
catchError(() => {
const fallback = this.createFallbackContent(cleanPath, targetLanguage);
return of(fallback.content || `# ${cleanPath}\n\nContent not available.`);
})
).toPromise();
MarkdownService.globalContentCache.set(globalContentKey, contentPromise);
MarkdownService.globalContentTimestamps.set(globalContentKey, now);
return from(contentPromise).pipe(
map(content => this.parseMarkdownContent(content, targetLanguage, cleanPath))
);
})
);
๐ฏ Benefits
1. Respects Manifest Extensions
- SearchService extracts correct extension from manifest
- MarkdownService now uses that extension directly
- No wasted requests trying wrong extension
2. Fallback Detection
- If no extension provided (e.g., from URL navigation)
- Calls
detectFileType()which prioritizes.mdcfor project routes - Smart detection based on route type (public vs project)
3. Circuit Breaker Prevention
- BEFORE: 11 requests for
.md, then tries.mdc(circuit breaker activates) - AFTER: 1 request for
.mdc(immediate success!)
๐ Expected Results
During Search Indexing
BEFORE (circuit breaker hell):
๐ Proxy: GET /docs/english/GoGrab-Pulse/index.md โ โ Try .md first (fail)
๐จ EMERGENCY CIRCUIT BREAKER ACTIVATED for index.md - 11 requests in 5s!
๐๏ธ Admin API: GET /docs/english/GoGrab-Pulse/index.mdc โ Then .mdc (success)
AFTER (clean):
๐ Using provided extension for: GoGrab-Pulse/index.mdc โ โ
Use .mdc directly
๐๏ธ Admin API: GET /docs/english/GoGrab-Pulse/index.mdc โ Success immediately!
During Normal Navigation
BEFORE (no extension in URL):
๐ Checking file type for project route: GoGrab-Pulse/index
๐ Trying .md first... โ โ Wrong priority
๐จ Circuit breaker after 11 failed requests
AFTER (smart detection):
๐ No extension in path, detecting file type for: GoGrab-Pulse/index
๐ Checking file type for project route: GoGrab-Pulse/index
๐ Found .mdc file for project file: GoGrab-Pulse/index โ โ
Correct priority
โ
Loaded successfully on first try!
๐งช Testing
To Verify Fix
Restart dev server:
npx nx reset && yarn nx serve docs-angularWait for build:
โ Browser application bundle generation complete.Hard refresh browser:
Cmd+Shift+R(Mac) orCtrl+Shift+F5(Windows)Check console logs:
- โ
๐ Using provided extension for: GoGrab-Pulse/index.mdc - โ NO "EMERGENCY CIRCUIT BREAKER" messages
- โ Search indexing completes in <2s (vs 30s+ before)
- โ
๐ Files Modified
apps/docs-angular/src/app/services/markdown.service.ts- Modified
loadContent()method (lines 374-440) - Added extension detection logic
- Integrated
detectFileType()for paths without extensions
- Modified
๐ Related Fixes
- Infinite Loop Path Duplication Fix - Fixed path transformation in SearchService
- Circuit Breaker Fix - Added circuit breaker to MarkdownService
- DetectFileType Priority Fix - Prioritized
.mdcfor project routes
โจ Summary
This fix completes the circuit breaker resolution by ensuring that:
- โ Extensions from manifest are respected
- โ Smart detection works for extensionless paths
- โ Zero wasted requests during search indexing
- โ Fast, efficient file loading across the entire app
Result: Circuit breaker activations should be completely eliminated for normal operation! ๐