{"record":{"id":"140d231b4f58f5c1","repo":"666ghj/MiroFish","slug":"error-140d23","errorCode":null,"errorMessage":"模拟停止失败","messagePattern":"模拟停止失败","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"backend/app/services/simulation_runner.py","lineNumber":1077,"sourceCode":"                            RunnerStatus.FAILED,\n                            state.error,\n                        )\n                        raise RuntimeError(state.error) from error\n                state.runner_status = RunnerStatus.STOPPED\n                state.twitter_running = False\n                state.reddit_running = False\n                state.completed_at = datetime.now().isoformat()\n                state.error = None\n                cls._save_run_state(state)\n                cls._sync_simulation_status(\n                    simulation_id,\n                    RunnerStatus.STOPPED,\n                )\n                cls._manual_stop_requests.discard(simulation_id)\n\n        state = cls.get_run_state(simulation_id) or state\n        if state.runner_status == RunnerStatus.FAILED:\n            raise RuntimeError(state.error or \"模拟停止失败\")\n        if state.runner_status != RunnerStatus.STOPPED:\n            raise RuntimeError(\n                f\"模拟停止未达到终态: {simulation_id}, status={state.runner_status}\"\n            )\n\n        logger.info(f\"模拟已停止: {simulation_id}\")\n        return state\n\n    @classmethod\n    def _read_actions_from_file(\n        cls,\n        file_path: str,\n        default_platform: Optional[str] = None,\n        platform_filter: Optional[str] = None,\n        agent_id: Optional[int] = None,\n        round_num: Optional[int] = None\n    ) -> List[AgentAction]:\n        \"\"\"","sourceCodeStart":1059,"sourceCodeEnd":1095,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/services/simulation_runner.py#L1059-L1095","documentation":"Generic RuntimeError raised by stop_simulation when, after termination, the (possibly refreshed) run state ends as FAILED but state.error is None/empty. It is a fallback message; normally the specific failure text is carried instead (see the branch above it that prefers state.error).","triggerScenarios":"Stop completes, state.runner_status == RunnerStatus.FAILED, and state.error was cleared or never set — e.g. an external writer (monitor thread or crash handler) set FAILED without a message, or a race cleared state.error between the FAILED assignment and this read.","commonSituations":"Rare defensive path; usually appears after custom patches that set runner_status = FAILED directly, or after a restart-recovery routine that reconstructs state without the error field.","solutions":["Search logs around the stop for the real cause (the monitor thread logged it before marking FAILED).","Audit any code that assigns RunnerStatus.FAILED directly to also set state.error.","Re-fetch the run state / simulation record for the persisted error message, which may not be in the in-memory copy."],"exampleFix":"# before\nstate.runner_status = RunnerStatus.FAILED\ncls._save_run_state(state)  # later stop_simulation raises bare 模拟停止失败\n\n# after\nstate.runner_status = RunnerStatus.FAILED\nstate.error = f\"monitor exit code {proc.returncode}\"\ncls._save_run_state(state)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    SimulationRunner.stop_simulation(sim_id)\nexcept RuntimeError as e:\n    state = SimulationRunner.get_run_state(sim_id)\n    if state and state.runner_status == RunnerStatus.FAILED:\n        # real cause is in logs / persisted record, not the exception text\n        handle_failed_run(sim_id)\n    else:\n        raise","preventionTips":["Always set state.error whenever setting runner_status = FAILED.","Log the failure cause at the point it is detected, not only at stop.","Include machine-readable failure reasons in the persisted simulation record."],"tags":["simulation","stop","failed-state","diagnostics"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}