{
  "id": 7340222,
  "title": "Where Recursion Ends: Render Limits for Untrusted UI",
  "url": "https://urgent.news/2026/09/14/where-recursion-ends-render-limits-for-untrusted-ui",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-14T14:56:27.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/shteynu/where-recursion-ends-render-limits-for-untrusted-ui-3oo3"
  },
  "original_language": "en",
  "account": "The author's previous article concluded with a list of features they believed a robust dynamic UI runtime should possess, including maximum graph depth, maximum rendered nodes, and explicit cycle protection. Implementing this list proved to be a valuable learning experience, revealing how many seemingly viable solutions are actually flawed. This article delves into the story behind ngx-json-render version 0.4.0, starting with a JSON specification containing just two elements. This minimal specification was sufficient to demonstrate the consequences of inadequate safeguards. Prior to version 0.4.0, the JSON-rendering process proceeded without issue when executed in strict or unstrict modes, rendering all elements without raising any errors. However, once the validation process was enabled, the runtime crashed due to a maximum call stack size exceeded error, rendering 143 elements before encountering the limit and causing the tab to freeze. The root cause of this issue was not within any single element, but rather in the way the runtime interpreted the entire structure. The JSON specification described a graph, which the rendering process treated as if it were a tree, leading to the improper handling of recursive structures. The conventional solution to prevent this crash was to implement cycle detection, tracking the ancestry of rendered elements and refusing to render any element that identified itself as its own ancestor. While this approach effectively halted the crash, it also broke the intended behavior of common UI components such as comment threads, file browsers, and nested menus. These components often utilize recursive structures, where elements refer to themselves indirectly through their children. The proper way to represent such recursive data in a JSON-render spec is by using a repeat mechanism with a relative path, allowing elements to render their children without triggering the cycle detection mechanism. This second fix, while seemingly more appropriate, also introduced its own issues. By comparing keys and repeat scopes instead of individual keys, the runtime inadvertently allowed elements to render themselves with different items each time, leading to unintended consequences in rendering. The key takeaway from this exploration is that structural validity and safety are distinct properties, and a JSON specification can satisfy the former without guaranteeing the latter. Developers must carefully consider the nuances of recursive data structures and their implications on rendering behavior. The next steps involve implementing a more nuanced solution that accommodates legitimate recursive patterns while maintaining robustness against improper usage.",
  "summary": "My last article ended on a list of things I thought a hardened dynamic UI runtime still needed: maximum graph depth, maximum rendered nodes, explicit cycle protection. Writing that list was the easy part. Building it turned out to be a lesson in how many wrong answers look right. This is that story, from ngx-json-render 0.4.0. It starts with a spec two elements long. Two elements are enough {…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}