From 72ca9cd5790e82f7a080e6f4e648aebdc597451f Mon Sep 17 00:00:00 2001 From: Andrey Cheptsov Date: Thu, 6 Aug 2026 18:27:06 +0200 Subject: [PATCH] Show failed creations in `dstack preset` A creation that ends as failed was dropped from the listing, so the only way back to its trials and log was to already know the preset id. `_STATUS_DISPLAY` already had a red `failed` entry that nothing could reach. Co-Authored-By: Claude Opus 5 (1M context) --- .../_internal/cli/services/presets/session.py | 2 +- .../_internal/cli/services/presets/test_create.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) 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"