Dashboard backup CLI argument flag bug

NousResearch/hermes-agent · cluster 54801 · dashboard

Data as of

Nothing open on GitHub. Fix merged in #64561. Check it covers your case.

The short answer

0open issues
0open PRs
7items grouped
Known?
Yes. 7 related items grouped here, 4 issues already closed.
Fix event
A fix was merged to main in PR #64561. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this partially resolved, deciding PR #64561. That is separate from the fix event.
Still open
Nothing open on GitHub.

The dashboard backup feature was passing the output path as a positional argument rather than using the correct -o/--output flag, causing backup failures. Multiple issue reports and fix attempts address this CLI argument syntax mismatch.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #64561 fix(dashboard): pass backup output path with -o instead of positional arg

    merged to main

    files: hermes_cli/web_server.py, tests/hermes_cli/test_dashboard_admin_endpoints.py, tests/hermes_cli/test_web_server.py

    Show the diff
    • hermes_cli/web_server.py
      @@ -11915,8 +11915,9 @@ def _new_dashboard_backup_path() -> Path:
       async def run_backup(body: BackupRequest):
           args = ["backup"]
           archive: Optional[Path] = None
      -    if body.output:
      -        args.append(body.output.strip())
      +    output = (body.output or "").strip()
      +    if output:
      +        args.extend(["-o", output])
           else:
               archive = _new_dashboard_backup_path()
               try:
      @@ -11926,7 +11927,7 @@ async def run_backup(body: BackupRequest):
                       status_code=500,
                       detail=f"Could not create backup directory: {exc}",
                   )
      -        args.append(str(archive))
      +        args.extend(["-o", str(archive)])
           try:
               proc = _spawn_hermes_action(args, "backup")
           except Exception as exc:
    • tests/hermes_cli/test_dashboard_admin_endpoints.py
      @@ -338,6 +338,60 @@ class TestOpsEndpoints:
           def _setup(self, _isolate_hermes_home):
               self.client, _ = _client()
       
      +    def test_backup_output_uses_output_flag(self, monkeypatch):
      +        import hermes_cli.web_server as ws
      +
      +        captured = {}
      +
      +        class FakeProc:
      +            pid = 12345
      +
      +        def fake_spawn_action(subcommand, name):
      +            captured["subcommand"] = subcommand
      +            captured["name"] = name
      +            return FakeProc()
      +
      +        monkeypatch.setattr(ws, "_spawn_hermes_action", fake_spawn_action)
      +
      +        r = self.client.post(
      +            "/api/ops/backup",
      +            json={"output": "  /tmp/hermes-test.zip  "},
      +        )
      +
      +        assert r.status_code == 200
      +        assert captured == {
      +            "subcommand": ["backup", "-o", "/tmp/hermes-test.zip"],
      +            "name": "backup",
      +        }
      +
      +    def test_backup_blank_output_uses_default_archive(self, monkeypatch):
      +        from pathlib import Path
      +
      +        import hermes_cli.web_server as ws
      +        from hermes_cli.config import get_hermes_home
      +
      +        captured = {}
      +
      +        class FakeProc:
      +            pid = 12345
      +
      +        def fake_spawn_action(subcommand, name):
      +            captured["subcommand"] = subcommand
      +            captured["name"] = name
      +            return FakeProc()
      +
      +        monkeypatch.setattr(ws, "_spawn_hermes_action", fake_spawn_action)
      +
      +        r = self.client.post("/api/ops/backup", json={"output": "   "})
      +
      +        assert r.status_code == 200
      +        archive = Path(r.json()["archive"])
      +        assert captured == {
      +            "subcommand": ["backup", "-o", str(archive)],
      +            "name": "backup",
      +        }
      +        assert archive.parent == get_hermes_home() / "backups"
      +
           def test_hooks_list_reads_config(self):
               from hermes_cli.config import load_config, save_config
       
    • tests/hermes_cli/test_web_server.py
      @@ -2385,7 +2385,7 @@ def fake_spawn(subcommand, name):
       
               assert data["name"] == "backup"
               assert captured["name"] == "backup"
      -        assert captured["args"] == ["backup", str(archive)]
      +        assert captured["args"] == ["backup", "-o", str(archive)]
               assert archive.parent == get_hermes_home() / "backups"
               assert archive.name.startswith("hermes-backup-")
               assert archive.suffix == ".zip"
      @@ -2412,7 +2412,7 @@ def fake_spawn(subcommand, name):
               archive = Path(resp.json()["archive"])
       
               assert archive.parent == hosted_home / "backups"
      -        assert captured["args"] == ["backup", str(archive)]
      +        assert captured["args"] == ["backup", "-o", str(archive)]
               assert archive.parent.is_dir()
       
           def test_ops_backup_download_streams_dashboard_backup(self, tmp_path):

2 PRs closed without merging

From the close comments: duplicate 1 · merged via another change 1

  • #55043 fix(dashboard): pass backup output with -o · merged via another change → #64561
  • #62631 fix(dashboard): pass --output to backup command · duplicate → #55043, #54801, #62489
Closed issues · 4
  • Closed#54801Dashboard backup button passes archive path as positional argument instead of --output flag
  • Closed#59078Dashboard backup passes output path as bare arg instead of -o
  • Closed#62489Backup error in macos App
  • Closed#65034Dashboard Full Backup fails silently in v0.18.2 — CLI argument syntax mismatch
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.25: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
dashboard
Merged PRs
#64561
Closed issues
4
Attempts
2 PRs closed without merging
Fix link checked
14 Jul 2026

For your agent

The same facts, typed.