hermes - 💡(How to fix) Fix [Bug] NameError: '_pool_may_recover_from_rate_limit' is not defined in conversation_loop.py

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…

When the eager-fallback path is triggered on a rate-limit error (HTTP 429 / quota exhaustion), agent/conversation_loop.py calls _pool_may_recover_from_rate_limit(...) directly. That function lives in run_agent.py, but conversation_loop.py imports run_agent only via the lazy _ra() helper — there is no top-level binding for _pool_may_recover_from_rate_limit in the file's namespace. The call raises:

NameError: name '_pool_may_recover_from_rate_limit' is not defined

…and crashes run_conversation for the entire turn.

Error Message

NameError: name '_pool_may_recover_from_rate_limit' is not defined

Root Cause

Introduced by commit 053025238 "refactor(run_agent): extract run_conversation to agent/conversation_loop.py" (2026-05-16).

The refactor moved run_conversation to agent/conversation_loop.py and replaced direct run_agent.<helper> references with _ra().<helper> (lazy import). It missed one call site:

# agent/conversation_loop.py:2254
pool_may_recover = _pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)

The function definition lives in run_agent.py:239, so the unprefixed reference is unbound in conversation_loop.py's namespace.

Fix Action

Fix

Wrap the call with _ra():

pool_may_recover = _ra()._pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)

PR with the one-line fix follows.

Code Example

NameError: name '_pool_may_recover_from_rate_limit' is not defined

---

model:
     default: deepseek-v4-flash-free
     provider: opencode-zen
   fallback_providers:
   - provider: openrouter
     model: deepseek/deepseek-v4-flash:free

---

ERROR root: run_conversation raised: name '_pool_may_recover_from_rate_limit' is not defined
       pool_may_recover = _pool_may_recover_from_rate_limit(
   NameError: name '_pool_may_recover_from_rate_limit' is not defined

---

# agent/conversation_loop.py:2254
pool_may_recover = _pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)

---

pool_may_recover = _ra()._pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)
RAW_BUFFERClick to expand / collapse

Version

Hermes Agent v0.14.0 (2026-05-16)

Summary

When the eager-fallback path is triggered on a rate-limit error (HTTP 429 / quota exhaustion), agent/conversation_loop.py calls _pool_may_recover_from_rate_limit(...) directly. That function lives in run_agent.py, but conversation_loop.py imports run_agent only via the lazy _ra() helper — there is no top-level binding for _pool_may_recover_from_rate_limit in the file's namespace. The call raises:

NameError: name '_pool_may_recover_from_rate_limit' is not defined

…and crashes run_conversation for the entire turn.

Reproduction

  1. Configure a fallback_providers chain where at least one provider returns HTTP 429 (rate limit) or HTTP 402 (billing/quota), e.g.:
    model:
      default: deepseek-v4-flash-free
      provider: opencode-zen
    fallback_providers:
    - provider: openrouter
      model: deepseek/deepseek-v4-flash:free
  2. Drive enough traffic to trigger a 429 (or use a provider already at quota).
  3. Observe the error in ~/.hermes/logs/agent.log:
    ERROR root: run_conversation raised: name '_pool_may_recover_from_rate_limit' is not defined
        pool_may_recover = _pool_may_recover_from_rate_limit(
    NameError: name '_pool_may_recover_from_rate_limit' is not defined

Root cause

Introduced by commit 053025238 "refactor(run_agent): extract run_conversation to agent/conversation_loop.py" (2026-05-16).

The refactor moved run_conversation to agent/conversation_loop.py and replaced direct run_agent.<helper> references with _ra().<helper> (lazy import). It missed one call site:

# agent/conversation_loop.py:2254
pool_may_recover = _pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)

The function definition lives in run_agent.py:239, so the unprefixed reference is unbound in conversation_loop.py's namespace.

Fix

Wrap the call with _ra():

pool_may_recover = _ra()._pool_may_recover_from_rate_limit(
    agent._credential_pool,
    provider=agent.provider,
    base_url=getattr(agent, "base_url", None),
)

PR with the one-line fix follows.

Impact

Any user with a fallback_providers chain that has at least one rate-limited / quota-exhausted provider is affected. The eager-fallback path was the documented escape valve from 429s (commit 1fc77f995 "fall back on rate limit when pool has no rotation room"); right now it actually makes the situation worse — instead of switching to the next provider, the whole turn errors out.

Environment

  • Hermes Agent v0.14.0 (2026.5.16)
  • Python 3.11.14
  • OpenAI SDK 2.24.0
  • macOS

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 [Bug] NameError: '_pool_may_recover_from_rate_limit' is not defined in conversation_loop.py