hermes - 💡(How to fix) Fix bug: 'Always Approve' for destructive slash commands silently fails when ruamel.yaml is missing from venv

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

if choice == "always": try: from cli import save_config_value save_config_value("approvals.destructive_slash_confirm", False) logger.info("User opted out of destructive slash confirm ...") except Exception as exc: logger.warning("Failed to persist destructive_slash_confirm=false: %s", exc)

Root Cause

save_config_value() in cli.py calls atomic_roundtrip_yaml_update() from utils.py, which imports ruamel.yaml. If ruamel.yaml is missing from the venv, the ImportError is caught and logged at ERROR level — but never surfaced to the user:

ERROR cli: Failed to save config: No module named 'ruamel'

The gateway code at gateway/run.py:12406-12420 catches exceptions from save_config_value and only logs a warning:

if choice == "always":
    try:
        from cli import save_config_value
        save_config_value("approvals.destructive_slash_confirm", False)
        logger.info("User opted out of destructive slash confirm ...")
    except Exception as exc:
        logger.warning("Failed to persist destructive_slash_confirm=false: %s", exc)

The info log fires before atomic_roundtrip_yaml_update actually executes (since it's called inside a try/except but the info log is outside the actual save), so the log says "opted out" regardless of whether the write succeeded. The user sees nothing wrong.

Fix Action

Fix / Workaround

  • #14714 — same function (save_config_value) has a different bug (wrong file target on first run)
  • #24701 — /new stalling issue where "Always Approve" is the documented workaround (but that workaround doesn't actually work when ruamel.yaml is missing)

Code Example

ERROR cli: Failed to save config: No module named 'ruamel'

---

if choice == "always":
    try:
        from cli import save_config_value
        save_config_value("approvals.destructive_slash_confirm", False)
        logger.info("User opted out of destructive slash confirm ...")
    except Exception as exc:
        logger.warning("Failed to persist destructive_slash_confirm=false: %s", exc)
RAW_BUFFERClick to expand / collapse

Bug Description

The "Always Approve" button on destructive slash commands (/new, /reset, /undo, /clear) silently fails to persist. The user clicks "Always Approve," the gateway logs "User opted out of destructive slash confirm," but the approvals.destructive_slash_confirm: false setting never lands in config.yaml. On next /new, the confirmation prompt reappears. The user can click "Always Approve" dozens of times with zero effect.

Root Cause

save_config_value() in cli.py calls atomic_roundtrip_yaml_update() from utils.py, which imports ruamel.yaml. If ruamel.yaml is missing from the venv, the ImportError is caught and logged at ERROR level — but never surfaced to the user:

ERROR cli: Failed to save config: No module named 'ruamel'

The gateway code at gateway/run.py:12406-12420 catches exceptions from save_config_value and only logs a warning:

if choice == "always":
    try:
        from cli import save_config_value
        save_config_value("approvals.destructive_slash_confirm", False)
        logger.info("User opted out of destructive slash confirm ...")
    except Exception as exc:
        logger.warning("Failed to persist destructive_slash_confirm=false: %s", exc)

The info log fires before atomic_roundtrip_yaml_update actually executes (since it's called inside a try/except but the info log is outside the actual save), so the log says "opted out" regardless of whether the write succeeded. The user sees nothing wrong.

Why ruamel.yaml can be missing

ruamel.yaml IS declared in pyproject.toml as a required dependency. However, on installs that predate uv or installations done via pip install -e ., transitive dependencies may not be fully resolved. In this case the venv had 300+ packages but ruamel.yaml was absent.

Steps to Reproduce

  1. Ensure ruamel.yaml is NOT installed in the Hermes venv: /path/to/venv/bin/python -c "import ruamel.yaml"ModuleNotFoundError
  2. In a gateway session (Telegram), type /new
  3. Click Always Approve
  4. Check ~/.hermes/config.yamldestructive_slash_confirm is not present
  5. Check ~/.hermes/logs/errors.log — contains Failed to save config: No module named 'ruamel'
  6. Type /new again — confirmation prompt still appears

Actual Behavior

  • Button appears to work (no visible error)
  • Gateway log says "User opted out of destructive slash confirm" (misleading)
  • Config is never written
  • User is stuck in a loop — can click "Always Approve" forever with no effect

Expected Behavior

Either:

  1. The dependency on ruamel.yaml is enforced so it's never missing (preferred)
  2. OR the failure is surfaced to the user with a clear error message ("Failed to save preference — missing dependency: ruamel.yaml")

Additionally: the "opted out" log line should fire after the save succeeds, not before.

Environment

  • Hermes Agent: installed via pip install -e . in venv
  • OS: Debian Linux
  • Python: 3.11
  • Gateway: Telegram

Related

  • #14714 — same function (save_config_value) has a different bug (wrong file target on first run)
  • #24701 — /new stalling issue where "Always Approve" is the documented workaround (but that workaround doesn't actually work when ruamel.yaml is missing)

Suggested Fix

Option A (preferred): Guard the import or add ruamel.yaml as a hard runtime check at startup — refuse to start or warn loudly if it's absent, since config persistence is critical.

Option B: Surface the error to the user. The _maybe_confirm_destructive_slash handler could return an error message if save_config_value returns False, or the exception handler could include the actual error in the reply: "⚠️ Failed to save preference: No module named 'ruamel'. Try: pip install ruamel.yaml"

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING