{"record":{"id":"5ab472a99251f757","repo":"usestrix/strix","slug":"unknown-agent-agent-id","errorCode":null,"errorMessage":"Unknown agent: {agent_id}","messagePattern":"Unknown agent: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"strix/interface/tui/backend/controller.py","lineNumber":389,"sourceCode":"            )\n        else:\n            future = asyncio.run_coroutine_threadsafe(\n                self.coordinator.send(\n                    agent_id,\n                    {\"from\": \"user\", \"content\": message, \"type\": \"instruction\"},\n                ),\n                self.scan_loop,\n            )\n            delivered = await asyncio.wrap_future(future)\n        if not delivered:\n            raise RuntimeError(\"Message could not be delivered\")\n        return {\"sent\": True}\n\n    async def _stop_agent(self, payload: dict[str, Any]) -> dict[str, Any]:\n        agent_id = self._required_string(payload, \"agent_id\")\n        agent = self.live_view.agents.get(agent_id)\n        if agent is None:\n            raise ValueError(f\"Unknown agent: {agent_id}\")\n        status = str(agent.get(\"status\", \"\"))\n        if status not in _STOPPABLE_AGENT_STATUSES:\n            raise RuntimeError(f\"Agent '{agent_id}' cannot be stopped while {status or 'unknown'}\")\n        if self.coordinator is None or self.scan_loop is None or self.scan_loop.is_closed():\n            raise RuntimeError(\"Scan loop is not ready\")\n        if self.scan_loop is asyncio.get_running_loop():\n            accepted = await self.coordinator.cancel_descendants_graceful(agent_id)\n        else:\n            future = asyncio.run_coroutine_threadsafe(\n                self.coordinator.cancel_descendants_graceful(agent_id), self.scan_loop\n            )\n            accepted = await asyncio.wrap_future(future)\n        if not accepted:\n            raise RuntimeError(f\"Agent '{agent_id}' is no longer active\")\n        return {\"stopped\": True}\n\n    async def _open_viewer(self, _payload: dict[str, Any]) -> dict[str, Any]:\n        if self.viewer_url:","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/tui/backend/controller.py#L371-L407","documentation":"Raised by _stop_agent when the supplied agent_id does not exist in live_view.agents, the controller's live snapshot of agents in the current scan. It is a ValueError (bad input) rather than a state error: the id itself is wrong before any stop machinery is consulted. Ids are exact strings, so any mismatch in casing, prefix, or staleness triggers it.","triggerScenarios":"Calling stop-agent with an id copied from a previous scan, a truncated id, or an id assembled by the frontend (e.g. missing a numeric suffix). The lookup is live_view.agents.get(agent_id) returning None.","commonSituations":"UI list is stale after agents spawned or finished; user pastes an agent id from an older run; automated scripts iterating a cached agent list; typo in hand-written ids.","solutions":["Re-read controller.live_view.agents and use an id that currently exists","Print the available agent ids on failure so the caller can self-correct","In scripts, always discover ids from the live view at call time instead of hardcoding","Verify the id matches exactly (case-sensitive, full string)"],"exampleFix":"# before\nawait controller._stop_agent({\"agent_id\": \"scanner\"})\n\n# after\nagents = controller.live_view.agents\nif \"scanner\" not in agents:\n    raise SystemExit(f\"unknown agent; available: {sorted(agents)}\")\nawait controller._stop_agent({\"agent_id\": \"scanner\"})","handlingStrategy":"validation","validationCode":"if agent_id not in controller.live_view.agents:\n    raise KeyError(f\"unknown agent {agent_id}; known: {sorted(controller.live_view.agents)}\")","typeGuard":"def is_known_agent(agents: dict, aid: str) -> bool:\n    return aid in agents","tryCatchPattern":"try:\n    await controller._stop_agent({\"agent_id\": aid})\nexcept ValueError as e:\n    if str(e).startswith(\"Unknown agent\"):\n        aid = pick_from(controller.live_view.agents)  # refresh id\n    else:\n        raise","preventionTips":["Discover agent ids from live_view at call time, never hardcode","Print available ids on lookup failure for quick self-correction","In scripts, re-fetch the agent list after any spawn/finish event"],"tags":["tui","validation","agent-lifecycle","input-error"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}