strix
strix copied to clipboard
fix: `RuntimeError: dictionary changed size during iteration` convert dictionary to list for stable iteration
I have fixed the RuntimeError: dictionary changed size during iteration in tui.py. The issue was caused by the UI thread iterating over tool_executions while the background agent thread was updating it. I modified the code to iterate over a copy of the dictionary, which is a standard thread-safe pattern for this scenario
before this PR:
└─$ ./run.sh
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /home/kali/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/strix/interface/tui.py:485 in _update_ui_from_tracer │
│ │
│ 482 │ │ if agent_updates: ╭────────────────────────────────────────────────────── locals ──────────────────────────────────────────────────────╮ │
│ 483 │ │ │ self._expand_all_agent_nodes() │ agent_data = { │ │
│ 484 │ │ │ │ 'id': 'agent_1a5d9682', │ │
│ ❱ 485 │ │ self._update_chat_view() │ │ 'name': 'UNION Column Counter', │ │
│ 486 │ │ │ │ 'task': 'Attempt column counting via UNION SELECT NULL injections and analyze responses f'+18, │ │
│ 487 │ │ self._update_agent_status_display() │ │ 'status': 'running', │ │
│ 488 │ │ 'parent_id': 'agent_a13c1c82', │ │
│ │ │ 'created_at': '2025-12-09T01:30:07.518493+00:00', │ │
│ │ │ 'updated_at': '2025-12-09T01:30:07.518523+00:00', │ │
│ │ │ 'tool_executions': [1063] │ │
│ │ } │ │
│ │ agent_id = 'agent_1a5d9682' │ │
│ │ agent_updates = True │ │
│ │ agents_tree = Tree(id='agents_tree') │ │
│ │ chat_history = VerticalScroll(id='chat_history') │ │
│ │ self = StrixTUIApp(title='strix', classes={'-dark-mode'}, pseudo_classes={'dark', 'blur'}) │ │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/kali/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/strix/interface/tui.py:556 in _update_chat_view │
│ │
│ 553 │ │ │ │ "Select an agent from the tree to see its activity.", "placeholder-no-ag ╭────────────────────────────────────────────── locals ──────────────────────────────────────────────╮ │
│ 554 │ │ │ ) │ chat_history = VerticalScroll(id='chat_history') │ │
│ 555 │ │ else: │ is_at_bottom = True │ │
│ ❱ 556 │ │ │ events = self._gather_agent_events(self.selected_agent_id) │ self = StrixTUIApp(title='strix', classes={'-dark-mode'}, pseudo_classes={'dark', 'blur'}) │ │
│ 557 │ │ │ if not events: ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ 558 │ │ │ │ content, css_class = self._get_chat_placeholder_content( │
│ 559 │ │ │ │ │ "Starting agent...", "placeholder-no-activity" │
│ │
│ /home/kali/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/strix/interface/tui.py:795 in _gather_agent_events │
│ │
│ 792 │ │ │ │ "id": f"tool_{exec_id}", │
│ 793 │ │ │ │ "data": tool_data, │
│ 794 │ │ │ } │
│ ❱ 795 │ │ │ for exec_id, tool_data in self.tracer.tool_executions.items() │
│ 796 │ │ │ if tool_data.get("agent_id") == agent_id │
│ 797 │ │ ] │
│ 798 │
│ │
│ ╭─────────────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ agent_id = 'agent_453f009b' │ │
│ │ chat_events = [ │ │
│ │ │ { │ │
│ │ │ │ 'type': 'chat', │ │
│ │ │ │ 'timestamp': '2025-12-08T22:08:33.704112+00:00', │ │
│ │ │ │ 'id': 'chat_420', │ │
│ │ │ │ 'data': { │ │
│ │ │ │ │ 'message_id': 420, │ │
│ │ │ │ │ 'content': 'To establish a filter/WAF blocking baseline by testing payloads directly in vuln'+602, │ │
│ │ │ │ │ 'role': 'assistant', │ │
│ │ │ │ │ 'agent_id': 'agent_453f009b', │ │
│ │ │ │ │ 'timestamp': '2025-12-08T22:08:33.704112+00:00', │ │
│ │ │ │ │ 'metadata': {} │ │
│ │ │ │ } │ │
│ │ │ }, │ │
│ │ │ { │ │
│ │ │ │ 'type': 'chat', │ │
│ │ │ │ 'timestamp': '2025-12-08T22:14:36.683759+00:00', │ │
│ │ │ │ 'id': 'chat_444', │ │
│ │ │ │ 'data': { │ │
│ │ │ │ │ 'message_id': 444, │ │
│ │ │ │ │ 'content': '', │ │
│ │ │ │ │ 'role': 'assistant', │ │
│ │ │ │ │ 'agent_id': 'agent_453f009b', │ │
│ │ │ │ │ 'timestamp': '2025-12-08T22:14:36.683759+00:00', │ │
│ │ │ │ │ 'metadata': {} │ │
│ │ │ │ } │ │
│ │ │ }, │ │
│ │ │ { │ │
│ │ │ │ 'type': 'chat', │ │
│ │ │ │ 'timestamp': '2025-12-08T22:17:24.936186+00:00', │ │
│ │ │ │ 'id': 'chat_455', │ │
│ │ │ │ 'data': { │ │
│ │ │ │ │ 'message_id': 455, │ │
│ │ │ │ │ 'content': '', │ │
│ │ │ │ │ 'role': 'assistant', │ │
│ │ │ │ │ 'agent_id': '[REDACTED]', │ │
│ │ │ │ │ 'timestamp': '2025-12-08T22:17:24.936186+00:00', │ │
│ │ │ │ │ 'metadata': {} │ │
│ │ │ │ } │ │
│ │ │ }, │ │
│ │ │ { │ │
│ │ │ │ 'type': 'chat', │ │
│ │ │ │ 'timestamp': '2025-12-08T22:22:24.264815+00:00', │ │
│ │ │ │ 'id': 'chat_477', │ │
│ │ │ │ 'data': { │ │
│ │ │ │ │ 'message_id': 477, │ │
│ │ │ │ │ 'content': '', │ │
│ │ │ │ │ 'role': 'assistant', │ │
│ │ │ │ │ 'agent_id': '[REDACTED]', │ │
│ │ │ │ │ 'timestamp': '2025-12-08T22:22:24.264815+00:00', │ │
│ │ │ │ │ 'metadata': {} │ │
│ │ │ │ } │ │
│ │ │ } │ │
│ │ ] │ │
│ │ self = StrixTUIApp(title='strix', classes={'-dark-mode'}, pseudo_classes={'dark', 'blur'}) │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: dictionary changed size during iteration
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────── 🛡️ STRIX CYBERSECURITY AGENT ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
│ 🦉 SESSION ENDED • Penetration test interrupted by user │
│ │
│ 🎯 Target: [REDACTED] │
│ 🔍 Vulnerabilities Found: HIGH: 1 (Total: 1) │
│ 🤖 Agents Used: 112 • 🛠️ Tools Called: 952 │
│ 📥 Input Tokens: 59.0M • 📤 Output Tokens: 139.1K │
│ │
│ 📊 Results Saved To: strix_runs/[REDACTED] │
│ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
error type: RuntimeError: dictionary changed size during iteration