Skip to content

[Bug] NameError: '_pool_may_recover_from_rate_limit' is not defined in conversation_loop.py #27370

@sherman-yang

Description

@sherman-yang

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/agentCore agent loop, run_agent.py, prompt buildertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions