ADR-049: AG Grid v34 circular context — event args filter
Date: 2026-02-20 Status: Accepted
Context
After switching to AG Grid Community and implementing rowClicked event handling, all
row-click events silently failed to reach Python. Playwright captured this browser error:
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'context' -> object with constructor 'Sr'
--- property 'beans' closes the circle
AG Grid v34 injects its internal GridContext object (which has a circular beans
reference) into event.context for all grid events. NiceGUI's aggrid.js
handle_event passes args.context verbatim to this.$emit(), and NiceGUI's
nicegui.js then attempts JSON.stringify of all event fields for socket.io transport,
triggering the circular reference error.
Two mitigations were applied:
-
Venv patch —
aggrid.jsline 65 was patched to wrapargs.contextin atry { JSON.parse(JSON.stringify(...)) } catch(e) { return null }IIFE. This prevents the error inside the component but is fragile (venv updates overwrite it). -
Event args filter (primary fix) — NiceGUI's
Element.on()accepts anargsparameter that tells the JavaScript layer which fields to include in the serialized event payload. By specifying only the fields our handlers actually need,contextis never included in the JSON.stringify call.
Decision
Use explicit args lists on all AG Grid event registrations:
grid.on("cellValueChanged", handler, args=["colId", "data", "newValue"])
grid.on("rowClicked", handler, args=["data", "rowIndex"])
This is the primary fix. The venv patch provides defense-in-depth but must not be relied upon as the sole protection.
Consequences
- Event handlers receive only the declared fields; any new field needed must be added to
the
argslist and thehandle_eventextracted properties inaggrid.js - The venv patch to
aggrid.jsmust be re-applied after any NiceGUI upgrade; document this in the upgrade checklist - Future AG Grid events added to the codebase must always declare an
argsfilter - This pattern should be considered whenever NiceGUI's
handle_eventis used with third-party Vue components that embed complex internal objects in event data