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

  1. โœ… SearchService correctly extracts .mdc from manifest
  2. โœ… SearchService passes path WITH .mdc to loadContent()
  3. โŒ loadContent() ignores the extension and hardcodes .md
  4. ๐Ÿšจ Circuit breaker activates (11 requests trying .md when 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

  1. Check if path has extension (.md or .mdc)
  2. If YES: Use the provided extension directly
  3. 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

2. Fallback Detection

3. Circuit Breaker Prevention


๐Ÿ“Š 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

  1. Restart dev server:

    npx nx reset && yarn nx serve docs-angular
    
  2. Wait for build:

    โœ” Browser application bundle generation complete.
    
  3. Hard refresh browser: Cmd+Shift+R (Mac) or Ctrl+Shift+F5 (Windows)

  4. 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

  1. 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

๐Ÿ”— Related Fixes


โœจ Summary

This fix completes the circuit breaker resolution by ensuring that:

  1. โœ… Extensions from manifest are respected
  2. โœ… Smart detection works for extensionless paths
  3. โœ… Zero wasted requests during search indexing
  4. โœ… Fast, efficient file loading across the entire app

Result: Circuit breaker activations should be completely eliminated for normal operation! ๐ŸŽ‰