Skip to content

fix(routing): asyncio.gather without return_exceptions=True leaks coroutines on partial document fetch failure #251

Closed

Description

@piyushmakhija28

Summary

route_query() in routing.py uses asyncio.gather(*fetch_coros) without return_exceptions=True. If any single document fetch raises DependencyUnavailable, asyncio.gather immediately propagates the exception and cancels all remaining in-flight fetch coroutines, leaving them un-awaited (resource leak) and giving the caller no way to distinguish a single-document transient error from a total outage.

Root Cause

backend/app/api/routing.py around line 95:

fetch_coros = [_fetch_doc(doc_id, tenant_id, store) for doc_id in document_ids]
docs = await asyncio..gather(*fetch_coros)   # ← no return_exceptions=True

When _fetch_doc raises for doc_id[0], the gather cancels doc_id[1..N]'s coroutines mid-flight, and those coroutines' async DB sessions may not be properly released.

Failure Scenario

  1. Caller submits document_ids=['doc_aaa', 'doc_bbb', 'doc_ccc'].
  2. DB connection drops intermittently; _fetch_doc('doc_aaa') raises DependencyUnavailable.
  3. asyncio.gather immediately propagates the exception; _fetch_doc('doc_bbb') and _fetch_doc('doc_ccc') are cancelled mid-flight.
  4. Caller receives 503. But doc_bbb and doc_ccc are perfectly accessible.
  5. Two SQLAlchemy async sessions are abandoned without close() → connection pool exhaustion under sustained traffic.

Proposed Fix

results = await asyncio.gather(*fetch_coros, return_exceptions=True)

# Separate exceptions from results:
docs = []
for doc_id, result in zip(document_ids, results):
    if isinstance(result, DependencyUnavailable):
        raise result          # re-raise infrastructure error
    elif isinstance(result, Exception):
        raise result          # unexpected error
    elif result is None:
        raise document_not_found(doc_id)   # now we know WHICH doc failed
    else:
        docs.append(result)

This guarantees all coroutines run to completion (or explicit error), sessions are properly released, and the 404 message correctly names the missing doc_id.

Activity

  1. added
    bugSomething isn't working
    priority: highData loss, security, or major correctness bug
    code-reviewFound via automated code review
    on Jun 21, 2026
  2. piyushmakhija28 commented on Jun 21, 2026

    @piyushmakhija28
    ContributorAuthor

    Fixed in PR #280 (Sprint R3/R4: fix(sprint-r3): root-cause fixes for all 39 bugs from code review round 3 + Sprint R4 round 4)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcode-reviewFound via automated code reviewpriority: highData loss, security, or major correctness bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions