hermes - 💡(How to fix) Fix RuntimeWarning: coroutine 'run_in_terminal.<locals>.run' was never awaited during /reload-mcp

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…

Running /reload-mcp emits a RuntimeWarning:

/Users/mcoddington/.hermes/hermes-agent/cli.py:12034: RuntimeWarning: coroutine 'run_in_terminal.<locals>.run' was never awaited

Error Message

import asyncio as _asyncio from prompt_toolkit.application import run_in_terminal

def _run_in_terminal_sync(func): """Fire-and-forget wrapper that properly schedules the coroutine.""" try: _asyncio.get_running_loop().create_task(run_in_terminal(func)) except RuntimeError: func()

Replace all bare run_in_terminal(...) with _run_in_terminal_sync(...)

Root Cause

prompt_toolkit.application.run_in_terminal() is an async function that returns a coroutine. The Hermes CLI calls it without awaiting at multiple locations in cli.py:

LineWhereCalled from context
1431cprint() — cross-thread print scheduling_schedule() callback, fired via loop.call_soon_threadsafe (line 1439). This is the primary suspect — triggered by any background-thread output (curator summaries, bg review 💾 … messages, etc.).
5717_run_curses_picker()Curses single-select modal (e.g. /profile)
5742_prompt_text_input()Free-text prompt inside modal
10970Ctrl+Z suspend handler (handle_ctrl_z)Suspend CLI to background

The warning's line number (12034 = n = len(submit_images)) is inside process_loop — the main event loop. This is because Python reports where the unawaited coroutine's lifecycle intersects with the active code path, not where it was created. The actual call creating the unawaited coroutine is line 1431 inside _schedule(), scheduled from call_soon_threadsafe at line 1439.

Code Example

/Users/mcoddington/.hermes/hermes-agent/cli.py:12034: RuntimeWarning: coroutine 'run_in_terminal.<locals>.run' was never awaited

---

import asyncio as _asyncio
from prompt_toolkit.application import run_in_terminal

def _run_in_terminal_sync(func):
    """Fire-and-forget wrapper that properly schedules the coroutine."""
    try:
        _asyncio.get_running_loop().create_task(run_in_terminal(func))
    except RuntimeError:
        func()

# Replace all bare run_in_terminal(...) with _run_in_terminal_sync(...)

---

import warnings
with warnings.catch_warnings():
    warnings.simplefilter("ignore", RuntimeWarning)
    run_in_terminal(_pick)
RAW_BUFFERClick to expand / collapse

Summary

Running /reload-mcp emits a RuntimeWarning:

/Users/mcoddington/.hermes/hermes-agent/cli.py:12034: RuntimeWarning: coroutine 'run_in_terminal.<locals>.run' was never awaited

Root Cause

prompt_toolkit.application.run_in_terminal() is an async function that returns a coroutine. The Hermes CLI calls it without awaiting at multiple locations in cli.py:

LineWhereCalled from context
1431cprint() — cross-thread print scheduling_schedule() callback, fired via loop.call_soon_threadsafe (line 1439). This is the primary suspect — triggered by any background-thread output (curator summaries, bg review 💾 … messages, etc.).
5717_run_curses_picker()Curses single-select modal (e.g. /profile)
5742_prompt_text_input()Free-text prompt inside modal
10970Ctrl+Z suspend handler (handle_ctrl_z)Suspend CLI to background

The warning's line number (12034 = n = len(submit_images)) is inside process_loop — the main event loop. This is because Python reports where the unawaited coroutine's lifecycle intersects with the active code path, not where it was created. The actual call creating the unawaited coroutine is line 1431 inside _schedule(), scheduled from call_soon_threadsafe at line 1439.

Why This Matters

  • Emits to stderr on every background-thread emission during /reload-mcp or normal use
  • Clutters logs and makes real errors harder to spot
  • A "never awaited" coroutine means the inner function (_pt_print) runs, but the async machinery is not properly awaited — relying on GC semantics rather than explicit lifecycle management

Reproduction Steps

  1. Start Hermes CLI (latest at ac51c4c1a)
  2. Run /reload-mcp in-session
  3. Observe the RuntimeWarning in stderr

Environment

  • Commit: ac51c4c1ad09a98c8c25d0b05009b3f387fd183d
  • OS: macOS

Suggested Fix

The cleanest fix is to wrap run_in_terminal calls in a helper that properly handles the coroutine:

import asyncio as _asyncio
from prompt_toolkit.application import run_in_terminal

def _run_in_terminal_sync(func):
    """Fire-and-forget wrapper that properly schedules the coroutine."""
    try:
        _asyncio.get_running_loop().create_task(run_in_terminal(func))
    except RuntimeError:
        func()

# Replace all bare run_in_terminal(...) with _run_in_terminal_sync(...)

Alternatively, suppress the warning explicitly if fire-and-forget is intentional:

import warnings
with warnings.catch_warnings():
    warnings.simplefilter("ignore", RuntimeWarning)
    run_in_terminal(_pick)

The first approach (using create_task) is preferred — it ensures the coroutine runs to completion via the event loop rather than relying on GC.

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

hermes - 💡(How to fix) Fix RuntimeWarning: coroutine 'run_in_terminal.<locals>.run' was never awaited during /reload-mcp