usestrix/strix · warning · RuntimeError
Scan is already starting or running
Error message
Scan is already starting or running
What it means
Raised by the TUI controller's _start handler (strix/interface/tui/backend/controller.py:299) when a setup.start command arrives while scan_started is already true or _start_in_progress is true. It is a re-entrancy guard: one scan per controller instance, and the async start sequence (which awaits _begin_scan) must not run twice concurrently.
Source
Thrown at strix/interface/tui/backend/controller.py:299
async def _add_target(self, payload: dict[str, Any]) -> dict[str, Any]:
self._require_setup_mutable()
target = self._required_string(payload, "target")
if target not in self.targets:
self.targets.append(target)
return {"target": target, "total": len(self.targets)}
async def _set_instruction(self, payload: dict[str, Any]) -> dict[str, Any]:
self._require_setup_mutable()
instruction = payload.get("instruction", "")
if not isinstance(instruction, str):
raise TypeError("instruction must be a string")
self.instruction = instruction.strip()
return {"instruction": self.instruction}
async def _start(self, payload: dict[str, Any]) -> dict[str, Any]:
if self.scan_started or self._start_in_progress:
raise RuntimeError("Scan is already starting or running")
# A bare prompt launches optimistically, like a coding agent: it skips
# the network model preflight and surfaces any model error live. A named
# target keeps the preflight so a real scan does not commit blind.
verify = payload.get("verify", True)
if not isinstance(verify, bool):
raise TypeError("verify must be a boolean")
# Launching with no target mounts the working directory, so it requires
# the user's explicit confirmation rather than happening silently.
mount_working_dir = payload.get("mount_working_dir", False)
if not isinstance(mount_working_dir, bool):
raise TypeError("mount_working_dir must be a boolean")
model = (load_settings().llm.model or "").strip()
if not model:
raise ValueError("No model configured. Set STRIX_LLM first.")
if self._on_start is None:
raise RuntimeError("Scan start is unavailable")
if not self.targets:
if not mount_working_dir:View on GitHub (pinned to 8551339130)
Solutions
- Treat it as benign in the UI: the first start is still progressing — do not retry, wait for the state change to 'preparing'/'running'.
- Debounce/guard the start button in the frontend (disable once clicked until scan_started flips).
- For programmatic drivers, poll a status/read endpoint and only send setup.start when no scan is active.
Example fix
// before
button.onClick = () => send("setup.start", {}); // double-click -> RuntimeError
// after
let started = false;
button.onClick = () => { if (!started) { started = true; send("setup.start", {}); } }; Defensive patterns
Strategy: try-catch
Validate before calling
if controller.scan_started or getattr(controller, '_start_in_progress', False):
print('scan already starting/running; ignoring extra start')
else:
await controller.handle("setup.start", {}) Type guard
def scan_is_idle(controller) -> bool:
return not controller.scan_started and not getattr(controller, '_start_in_progress', False) Try / catch
try:
await controller.handle("setup.start", {})
except RuntimeError as exc:
if 'already starting or running' in str(exc):
pass # benign duplicate start; first one is still in flight
else:
raise Prevention
- Disable the start button immediately after the first press.
- Drive programmatic starts from a state poll, not a timer.
- Treat this specific message as idempotent-start feedback, not an error.
When it happens
Trigger: Double-pressing Enter/Start in the TUI before the first press finishes preparing; a frontend retry on slow ack sending setup.start again; racing the workspace-mount confirmation path which also flips scan_started.
Common situations: Slow model preflight making users click start twice; frontend event handlers not debounced; scripted clients firing start on a timer without checking state.
Related errors
- No mount confirmation is pending
- Message could not be delivered
- Agent '{agent_id}' is no longer active
- The interactive interface could not start: {exc}
- Unknown command: {command}
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/8524b7ed864b5665.
Report an issue: GitHub.