diff --git a/src/dstack/_internal/cli/services/presets/session.py b/src/dstack/_internal/cli/services/presets/session.py index eb66f8112..3be48aefe 100644 --- a/src/dstack/_internal/cli/services/presets/session.py +++ b/src/dstack/_internal/cli/services/presets/session.py @@ -424,7 +424,7 @@ def list_agent_sessions() -> list[dict[str, Any]]: path = session.path manifest = session.read_manifest() status = manifest.get("status") - if status not in ("running", "interrupted", "success"): + if status not in ("running", "interrupted", "success", "failed"): continue if status == "running" and not session_process_alive(manifest): status = "interrupted" diff --git a/src/tests/_internal/cli/services/presets/test_create.py b/src/tests/_internal/cli/services/presets/test_create.py index 3297f21d9..81964905d 100644 --- a/src/tests/_internal/cli/services/presets/test_create.py +++ b/src/tests/_internal/cli/services/presets/test_create.py @@ -833,6 +833,20 @@ def test_load_agent_session_reads_any_status(self, tmp_path, monkeypatch): with pytest.raises(CLIError, match="Unknown preset"): load_agent_session("nope0000") + def test_lists_a_failed_session(self, tmp_path, monkeypatch): + from dstack._internal.cli.services.presets.session import list_agent_sessions + + self._session(tmp_path, "dead0000", "failed", "[t] boom\n") + self._session(tmp_path, "beef0000", "success", "[t] saved preset\n") + monkeypatch.setattr( + "dstack._internal.cli.services.presets.session.get_presets_dir", + lambda: tmp_path, + ) + + listed = {entry["id"]: entry["status"] for entry in list_agent_sessions()} + + assert listed == {"dead0000": "failed", "beef0000": "success"} + def test_print_session_log_dumps_log_verbatim(self, tmp_path, monkeypatch, capsys): session = self._session( tmp_path, "abcd0000", "success", "[t] trial 1 done\n[t] saved preset\n"