iflytek/astron-agent · error · Exception

Session closed and retry failed

Error message

Session closed and retry failed: {error}

What it means

When an aiohttp session has been closed underneath an in-flight request, _make_request retries via _handle_session_error, which clears the cached global session. If the failure still occurs on the last allowed retry (attempt == max_retries - 1), it raises Exception('Session closed and retry failed: {error}'), signaling that session recycling did not recover the connection.

Solutions

  1. Call cleanup_session() (or recreate the session) after loop/session lifecycle events and re-issue the request
  2. Reduce session reuse issues by checking session.closed before reuse and proactively recreating
  3. Investigate why the underlying error repeated across retries (server availability, proxy timeouts)
  4. If keepalive is the cause, tune server/aiohttp keepalive timeouts so idle sessions are refreshed before the server drops them

Example fix

# before
await ragflow_retrieve(dataset_id, query)
# after
try:
    await ragflow_retrieve(dataset_id, query)
except Exception as e:
    if 'Session closed' in str(e):
        await cleanup_session()
        result = await ragflow_retrieve(dataset_id, query)
Defensive patterns

Strategy: retry

Validate before calling

import aiohttp
from core.knowledge.infra.ragflow import ragflow_client as rc
async def session_usable() -> bool:
    s = rc._session_cache
    return s is not None and not s.closed

Try / catch

try:
    result = await ragflow_call(...)
except Exception as e:
    if 'Session closed and retry failed' in str(e):
        await cleanup_session()
        result = await ragflow_call(...)  # fresh session

Prevention

When it happens

Trigger: Calling any _make_request-backed RAGFlow operation while the cached aiohttp ClientSession is closed (e.g. after event-loop shutdown/restart, keepalive timeout on the server, or session garbage collection), and retries are exhausted.

Common situations: Long-lived service whose cached session outlived server keepalive; tests closing the loop/session between cases; deploying code that recreates the event loop while the module-level _session_cache persists; RAGFlow server restarting and dropping keepalive connections.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/f4f89c5a5bd3d649. Report an issue: GitHub.

Appendix: source

Thrown at core/knowledge/infra/ragflow/ragflow_client.py:302

    attempt: int, max_retries: int, error: Exception
) -> None:
    """
    Handle session closed errors with retry logic

    Args:
        attempt: Current attempt number
        max_retries: Maximum retry attempts
        error: The error that occurred

    Raises:
        Exception: If max retries exceeded
    """
    global _session_cache
    _session_cache = None
    logger.warning(f"Session closed, retrying... (attempt {attempt + 1}/{max_retries})")

    if attempt == max_retries - 1:
        raise Exception(f"Session closed and retry failed: {error}")
    return None  # This should never be reached but satisfies mypy


async def _make_request(
    method: str,
    endpoint: str,
    data: Optional[Dict[str, Any]] = None,
    files: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """
    Common function for sending HTTP requests

    Args:
        method: HTTP method
        endpoint: API endpoint
        data: Request data
        files: File data

View on GitHub (pinned to 5e758547a8)