HTTP

508 - Loop Detected

Hitting a 508 Loop Detected means the server found an infinite loop while processing your request—circular references in resource structures, recursive operations that never terminate, or WebDAV depth infinity requests that create loops. This server-side error (5xx) happens when server logic detects it's stuck in a loop. Most common in WebDAV PROPFIND requests with depth infinity on circular structures, but also appears when recursive operations hit circular references, resource trees have cycles, or server processing logic creates loops.

#Common Causes

  • Frontend: WebDAV PROPFIND with depth infinity on circular structure. Recursive resource fetching hits circular references. Client requests create server-side loops.
  • Backend: WebDAV depth infinity request on circular directory structure. Recursive operation without cycle detection. Resource tree has circular references. Server processing logic creates infinite loop.
  • Infrastructure: File system has circular symlinks. Directory structure creates loops. Resource storage has circular dependencies.

Solutions

  1. 1Step 1: Diagnose - Check DevTools Network tab—508 responses indicate server detected a loop. Review request parameters (especially depth for WebDAV). Check if recursive requests are involved.
  2. 2Step 2: Diagnose - Server logs show where the loop was detected. Review WebDAV depth settings. Check resource structure for cycles. Examine recursive operation logic.
  3. 3Step 3: Fix - Client-side: Use limited depth instead of infinity for WebDAV. Implement cycle detection in recursive operations. Add depth limits to requests.
  4. 4Step 4: Fix - Server-side: Implement cycle detection in recursive operations. Limit WebDAV depth processing. Add loop detection to resource traversal. Fix circular references in data.
  5. 5Step 5: Fix - Infrastructure: Fix circular symlinks in file system. Resolve circular directory structures. Review resource storage for cycles.

</>Code Examples

Fetch API: Prevent Loops in Recursive Operations
1// Client-side: Prevent loops with depth limits and cycle detection
2async function fetchResourceTree(path, depth = 0, maxDepth = 10, visited = new Set()) {
3  // Prevent infinite loops
4  if (depth > maxDepth) {
5    throw new Error('Maximum depth exceeded');
6  }
7  
8  // Cycle detection
9  if (visited.has(path)) {
10    throw new Error('Circular reference detected');
11  }
12  
13  visited.add(path);
14  
15  try {
16    // Use limited depth for WebDAV PROPFIND
17    const response = await fetch(`/api/resources?path=${encodeURIComponent(path)}&depth=${maxDepth - depth}`);
18    
19    if (response.status === 508) {
20      console.error('Loop detected in resource tree by server');
21      // Return partial results instead of continuing
22      return { 
23        path, 
24        children: [], 
25        error: 'Loop detected',
26        partial: true,
27        message: 'Server detected circular reference in resource structure',
28      };
29    }
30    
31    const data = await response.json();
32    
33    // Recursively fetch children with depth limit and cycle detection
34    if (data.children && depth < maxDepth) {
35      data.children = await Promise.all(
36        data.children.map(child => 
37          fetchResourceTree(
38            child.path, 
39            depth + 1, 
40            maxDepth,
41            new Set(visited) // Pass copy to prevent false positives
42          )
43        )
44      );
45    }
46    
47    return data;
48  } catch (error) {
49    console.error('Error fetching resource:', error);
50    throw error;
51  }
52}
53
54// WebDAV PROPFIND with depth limit
55async function propfindWithDepthLimit(url, maxDepth = 5) {
56  const response = await fetch(url, {
57    method: 'PROPFIND',
58    headers: {
59      'Depth': maxDepth.toString(), // Don't use 'infinity'
60      'Content-Type': 'application/xml',
61    },
62    body: `<?xml version="1.0"?><propfind xmlns="DAV:"><prop><displayname/></prop></propfind>`,
63  });
64  
65  if (response.status === 508) {
66    throw new Error('Loop detected - reduce depth or fix circular references');
67  }
68  
69  return response.text();
70}
Express.js: Detect and Prevent Loops
1// Server-side: Detect loops and return 508
2const express = require('express');
3const app = express();
4
5// Loop detection for recursive operations
6const detectLoops = (req, res, next) => {
7  const depth = parseInt(req.headers['depth'] || '0');
8  const maxDepth = 10;
9  
10  if (depth > maxDepth) {
11    return res.status(508).json({
12      error: 'Loop Detected',
13      message: 'Maximum depth exceeded',
14      maxDepth: maxDepth,
15    });
16  }
17  
18  // Track visited paths to detect cycles
19  const visitedPaths = req.visitedPaths || new Set();
20  const currentPath = req.path;
21  
22  if (visitedPaths.has(currentPath)) {
23    return res.status(508).json({
24      error: 'Loop Detected',
25      message: 'Circular reference detected in resource structure',
26      path: currentPath,
27    });
28  }
29  
30  visitedPaths.add(currentPath);
31  req.visitedPaths = visitedPaths;
32  
33  next();
34};
35
36// WebDAV PROPFIND handler with loop detection
37app.propfind('/api/resources/*', detectLoops, async (req, res) => {
38  const depth = parseInt(req.headers['depth'] || '0');
39  const path = req.params[0];
40  
41  // Don't allow infinity depth
42  if (req.headers['depth'] === 'infinity') {
43    return res.status(508).json({
44      error: 'Loop Detected',
45      message: 'Depth infinity not allowed - use limited depth',
46      suggestion: 'Use depth=5 or less',
47    });
48  }
49  
50  try {
51    const resources = await getResourcesRecursive(path, depth, req.visitedPaths);
52    res.set('Content-Type', 'application/xml');
53    res.send(generatePROPFINDResponse(resources));
54  } catch (error) {
55    if (error.message.includes('circular')) {
56      return res.status(508).json({
57        error: 'Loop Detected',
58        message: error.message,
59      });
60    }
61    throw error;
62  }
63});
64
65async function getResourcesRecursive(path, maxDepth, visited = new Set(), currentDepth = 0) {
66  if (currentDepth >= maxDepth) {
67    return [];
68  }
69  
70  if (visited.has(path)) {
71    throw new Error('Circular reference detected');
72  }
73  
74  visited.add(path);
75  const resources = await db.resources.findByPath(path);
76  
77  if (currentDepth < maxDepth) {
78    for (const resource of resources) {
79      resource.children = await getResourcesRecursive(
80        resource.path,
81        maxDepth,
82        new Set(visited),
83        currentDepth + 1
84      );
85    }
86  }
87  
88  return resources;
89}
Nginx: Limit WebDAV Depth
1# Nginx: Configure WebDAV with depth limits
2server {
3    listen 80;
4    server_name api.example.com;
5    
6    location /api/resources/ {
7        # Proxy to WebDAV backend
8        proxy_pass http://webdav-backend;
9        proxy_set_header Host $host;
10        proxy_set_header Depth $http_depth;
11        
12        # Limit depth to prevent loops
13        if ($http_depth = "infinity") {
14            return 508 '{"error":"Loop Detected","message":"Depth infinity not allowed"}';
15            default_type application/json;
16        }
17        
18        # Or modify depth header
19        # set $depth $http_depth;
20        # if ($depth = "") {
21        #     set $depth "0";
22        # }
23        # proxy_set_header Depth $depth;
24    }
25}

Related Errors

Provider Information

This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.

508 - Loop Detected | HTTP Error Reference | Error Code Reference