666ghj/MiroFish · error · ValueError
模拟配置不存在,请先调用 /prepare 接口
Error message
模拟配置不存在,请先调用 /prepare 接口
What it means
Raised in SimulationRunner (class method starting a run): it looks for simulation_config.json under the run-state directory for the simulation id, and if the file is absent raises ValueError telling the user to call /prepare first. The run stage depends on artifacts (config JSON, profiles) produced by the earlier prepare stage; running without them is a workflow-order violation.
Source
Thrown at backend/app/services/simulation_runner.py:397
"""
启动模拟
Args:
simulation_id: 模拟ID
platform: 运行平台 (twitter/reddit/parallel)
max_rounds: 最大模拟轮数(可选,用于截断过长的模拟)
enable_graph_memory_update: 是否将Agent活动动态更新到Zep图谱
graph_id: Zep图谱ID(启用图谱更新时必需)
Returns:
SimulationRunState
"""
# 加载模拟配置
sim_dir = os.path.join(cls.RUN_STATE_DIR, simulation_id)
config_path = os.path.join(sim_dir, "simulation_config.json")
if not os.path.exists(config_path):
raise ValueError(f"模拟配置不存在,请先调用 /prepare 接口")
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
# 初始化运行状态
time_config = config.get("time_config", {})
total_hours = time_config.get("total_simulation_hours", 72)
minutes_per_round = time_config.get("minutes_per_round", 30)
total_rounds = int(total_hours * 60 / minutes_per_round)
# 如果指定了最大轮数,则截断
if max_rounds is not None and max_rounds > 0:
original_rounds = total_rounds
total_rounds = min(total_rounds, max_rounds)
if total_rounds < original_rounds:
logger.info(f"轮数已截断: {original_rounds} -> {total_rounds} (max_rounds={max_rounds})")
state = SimulationRunState(View on GitHub (pinned to b5b53acc57)
Solutions
- Call the /prepare endpoint for this simulation and wait for success before starting the run.
- If prepare failed, read its error (state.error) and fix the underlying cause first (often errors 32/33/30).
- Verify simulation_config.json exists under the runner's RUN_STATE_DIR/<simulation_id>/; if the directory moved, align prepare and runner paths.
- In the UI, disable the run action until prepare reports success.
Example fix
# before
runner.start_simulation(sim_id, ...) # ValueError: 模拟配置不存在
# after
config_path = os.path.join(SimulationRunner.RUN_STATE_DIR, sim_id, 'simulation_config.json')
if not os.path.exists(config_path):
manager.prepare_simulation(sim_id, ...) # produce config first
runner.start_simulation(sim_id, ...) Defensive patterns
Strategy: validation
Validate before calling
config_path = os.path.join(SimulationRunner.RUN_STATE_DIR, simulation_id, 'simulation_config.json')
if not os.path.exists(config_path):
raise HTTPException(409, 'prepare must complete before starting the run') Try / catch
try:
SimulationRunner.start_simulation(sim_id, ...)
except ValueError as e:
if '请先调用 /prepare' in str(e):
raise HTTPException(409, str(e)) from e
raise Prevention
- Enforce the prepare->run workflow in the UI (disable run until prepare succeeds).
- Check prepare's persisted status/error before allowing start.
- Keep prepare artifacts and run state on the same persistent volume.
When it happens
Trigger: Calling start/run on a simulation whose prepare never completed or failed (e.g. failed at error 33); prepare wrote config to a different directory than RUN_STATE_DIR/simulation_id; state directory reset between prepare and run; wrong simulation_id.
Common situations: Frontend lets the user press 'run' before prepare finishes; prepare failed silently and the user retried the wrong stage; container/volume mismatch losing prepared artifacts; concurrent env reset.
Related errors
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/53c721b45f4cb5c8.
Report an issue: GitHub.