{"record":{"id":"b0fd057e77cbdb71","repo":"usestrix/strix","slug":"mount-working-dir-must-be-a-boolean","errorCode":null,"errorMessage":"mount_working_dir must be a boolean","messagePattern":"mount_working_dir must be a boolean","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"strix/interface/tui/backend/controller.py","lineNumber":310,"sourceCode":"        if not isinstance(instruction, str):\n            raise TypeError(\"instruction must be a string\")\n        self.instruction = instruction.strip()\n        return {\"instruction\": self.instruction}\n\n    async def _start(self, payload: dict[str, Any]) -> dict[str, Any]:\n        if self.scan_started or self._start_in_progress:\n            raise RuntimeError(\"Scan is already starting or running\")\n        # A bare prompt launches optimistically, like a coding agent: it skips\n        # the network model preflight and surfaces any model error live. A named\n        # target keeps the preflight so a real scan does not commit blind.\n        verify = payload.get(\"verify\", True)\n        if not isinstance(verify, bool):\n            raise TypeError(\"verify must be a boolean\")\n        # Launching with no target mounts the working directory, so it requires\n        # the user's explicit confirmation rather than happening silently.\n        mount_working_dir = payload.get(\"mount_working_dir\", False)\n        if not isinstance(mount_working_dir, bool):\n            raise TypeError(\"mount_working_dir must be a boolean\")\n        model = (load_settings().llm.model or \"\").strip()\n        if not model:\n            raise ValueError(\"No model configured. Set STRIX_LLM first.\")\n        if self._on_start is None:\n            raise RuntimeError(\"Scan start is unavailable\")\n        if not self.targets:\n            if not mount_working_dir:\n                raise ValueError(\"No target set. Add a target first.\")\n            # Mounting the working directory needs the user's confirmation, and\n            # that is asked in the live view. Enter it now and prepare nothing\n            # until the answer arrives, so declining leaves no run behind.\n            self.pending_workspace_mount = str(Path.cwd())\n            self._pending_verify = verify\n            self.setup_mode = False\n            self.scan_started = True\n            self.scan_state = \"preparing\"\n            return {\"started\": True}\n        await self._begin_scan(verify)","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/tui/backend/controller.py#L292-L328","documentation":"Raised by _start in the TUI controller (strix/interface/tui/backend/controller.py:310) when the 'mount_working_dir' payload field (default false, which allows launching with no target by mounting the current working directory after user confirmation) is present but not a bool. Same strict-boolean trust-boundary check as 'verify': JSON numbers/strings are rejected with TypeError.","triggerScenarios":"Sending setup.start with {\"mount_working_dir\": 1} or \"true\"; UIs mapping a checkbox to an integer state; automation pipelines forwarding string flags.","commonSituations":"Checkbox state serialized as 0/1 by form libraries; shell-driven clients passing \"false\" as a literal string.","solutions":["Send a real JSON boolean ({\"mount_working_dir\": true}) or omit the field for the default false.","Coerce before dispatch: Boolean(mount) in the sender.","Unit-test the payload shape alongside the UI toggle."],"exampleFix":"// before\nsend(\"setup.start\", { mount_working_dir: 1 });\n\n// after\nsend(\"setup.start\", { mount_working_dir: mountCheckbox.checked });","handlingStrategy":"type-guard","validationCode":"mount = payload.get(\"mount_working_dir\", False)\nif not isinstance(mount, bool):\n    payload[\"mount_working_dir\"] = bool(mount)","typeGuard":"def has_boolean_mount_flag(payload: dict) -> bool:\n    return \"mount_working_dir\" not in payload or isinstance(payload[\"mount_working_dir\"], bool)","tryCatchPattern":"try:\n    await controller.handle(\"setup.start\", payload)\nexcept TypeError as exc:\n    if 'mount_working_dir must be a boolean' in str(exc):\n        payload[\"mount_working_dir\"] = bool(payload[\"mount_working_dir\"])\n        await controller.handle(\"setup.start\", payload)\n    else:\n        raise","preventionTips":["Bind mount toggles to native booleans in the UI layer.","Never forward raw string flags from CLI/config into payloads."],"tags":["tui","type-validation","payload","workspace-mount"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}