General interview: When is HTTP 508 Loop Detected correct, and how do you prevent WebDAV traversal cycles?
Prompt and scope
A WebDAV service allows multiple bindings between collections. A client sends a PROPFIND with Depth: infinity; the server reaches a collection already on the traversal path and returns 508. Explain the exact meaning of 508, distinguish it from a generic retry loop, describe when 208 Already Reported is appropriate, prevent resource exhaustion, and define client behavior.
This combines HTTP status semantics, graph traversal, protocol compatibility, and security boundaries. RFC 5842 defines 508 for terminating an infinite-depth operation after a loop is encountered; IANA registers 508 under RFC 5842.
What the interviewer is testing
- Whether you know 508 is about WebDAV bindings and
Depth: infinity, not any redirect failure. - Whether you can model resources, URI bindings, paths, and visited collections as a graph.
- Whether you distinguish continuing with 208 for a repeated resource from failing the whole operation with 508 when the client lacks 208 support.
- Whether you provide deterministic termination, budgets, observability, and fallback rather than only saying “add a visited set.”
Questions to clarify first
- What method and Depth value are used? The semantics concern recursive traversal.
- Does the server implement RFC 5842 bindings and advertise DAV capabilities? Does the client understand 208?
- Is a node deduplicated by resource ID, canonical URI, or binding path? One resource can have multiple URIs.
- Should the response contain partial results, or must the operation fail atomically?
- What node, body-size, CPU-time, and authorization budgets constrain hostile deep traversals?
A 30-second answer framework
First constrain the meaning: 508 says a server terminated a WebDAV Depth: infinity operation after finding a binding cycle; it is not a generic HTTP retry status. Model bindings as a graph and detect back edges by resource identity. If the client understands 208, report a resource once and continue a multistatus response; otherwise 508 can clearly fail the operation. Apply node, depth, byte, and time budgets, record the cycle, and stop automatic client retries.
Step-by-step answer
1. Model the resource graph, not only URL strings
Nodes are resources or collections and edges are bindings. A URI is an access path, not necessarily a resource identity; one resource can have several bindings. Keep resource ID, current path, and parent path for deduplication, audit, and diagnosis.
2. Use explicit DFS or BFS state
Maintain the active recursion stack and a reported set. Before entering a node, check whether it is already on the active stack; that is a back edge. Reaching the same resource through another path can be treated as already reported according to protocol capability rather than expanded forever.
visit(node, path):
if node in activePath: return CYCLE
if node in reported: return ALREADY_REPORTED
budget.consume(node)
activePath.add(node)
report(node)
for child in children(node): visit(child, path + child)
activePath.remove(node)activePath identifies a real cycle, while reported prevents duplicate output through multiple bindings. One set cannot safely represent both cases.
3. Select 208 or 508 from client capability
If the client advertises support for the binding extension and 208, the server can return the first occurrence normally, mark later bindings Already Reported in a multistatus response, and omit their descendants. If the client does not understand 208, RFC 5842 provides a compatibility path in which the infinite-depth operation fails with 508. Do not disguise the failure as 200.
4. Set deterministic budgets and security boundaries
Even an acyclic graph can exhaust CPU, memory, or response space. Set maximum nodes, active-path length, total bytes, wall-clock time, and concurrency. On budget exhaustion, record the reason and return a clear allowed failure rather than retrying. Check authorization across tenant bindings so hidden nodes do not leak through a multistatus response.
5. Handle writes and concurrent topology changes
BIND, REBIND, and UNBIND change the graph. Traverse a consistent snapshot or version so a topology change cannot invalidate detection mid-operation. Before creating a possibly cyclic binding, run a reachability check or require an explicit cycle-allowed precondition; keep check and commit in one transaction boundary.
6. Make clients stop harmful retries
508 means the requested operation failed; clients should not treat it like 503 and blindly retry with backoff. Read the body and correlation ID, reduce depth, repair the binding, or query capabilities. A proxy that maps 508 into a common error must preserve the original status and diagnostic fields.
High-quality sample answer
I would model bindings as a directed graph and distinguish resource identity from access URI. For Depth: infinity, use the active recursion stack to detect back edges and a reported set to suppress duplicate output when multiple bindings reach the same resource; those sets have different meanings. Traverse a consistent view with node, depth, response-byte, and time budgets.
When a client advertises RFC 5842 and 208 support, return the first resource in a 207 multistatus response, mark later duplicates Already Reported, and omit their descendants. For a client that does not understand 208, terminate the entire infinite-depth operation with 508 as specified by the compatibility path. 508 is not a generic retry error, so clients should stop automatic retries and repair the graph or lower depth. Enforce authorization, metrics, and correlation logs to keep cycles and deep traversals from becoming DoS vectors.
Common failure modes
- Calling 508 a reverse-proxy retry exhaustion or a generic URL redirect loop.
- Deduplicating only by URI string and missing multiple bindings to one resource.
- Using only a global visited set, confusing shared resources with back edges, or losing the 208/508 distinction.
- Accepting
Depth: infinitywithout node, byte, time, and authorization budgets. - Automatically retrying 508 and repeatedly spending resources on the same topology.
- Forgetting capability negotiation, 207 multistatus responses, or write races.
Follow-up questions and reference answers
What is the boundary between 508 and 208?
208 reports a previously seen resource when the client understands the binding extension, allowing the rest of the operation to continue. 508 terminates the whole infinite-depth operation after a cycle, commonly for a client that cannot use 208.
Why not use only a URI as the visited key?
Several URIs can bind to one resource, so URI-only tracking repeats traversal. The path still matters for diagnosis, so keep both resource identity and path context.
How do you avoid TOCTOU between a check and a write?
Run reachability validation and binding commit in one transaction or versioned snapshot. If atomicity spans nodes, fail on a version condition and recheck.
Should a client retry after 508?
Not blindly. The current topology made the operation fail; reduce depth, repair the cycle, or obtain capability information. Retry only after the topology has changed deliberately.
How do you test for false-positive cycle detection?
Use fixtures for an acyclic DAG, a shared resource, a binding cycle, and a depth limit. Assert result counts, status codes, traversal budgets, audit logs, and response-size limits.
Does 508 apply to every microservice call cycle?
No. Its standardized meaning comes from WebDAV RFC 5842. Other service loops need their own error contract; retaining a 5xx does not make the response WebDAV 508 semantics.