Skip to content

Investigate official per-request retry control for recovered Gemini conversations #77

Description

@Amm1rr

Investigate Per-Request Retry Control for Recovered Gemini Conversations

Summary

Recovered Gemini conversation requests can correctly return HTTP 410 when a local snapshot exists but the remote Gemini thread is no longer recoverable.

However, gemini_webapi currently retries APIError internally via @running(retry=5) before the final exception reaches our mapping layer.

As a result, the API now returns the correct response, but users still experience unnecessary latency and noisy logs before receiving the final HTTP 410 response.

Current Behavior

Missing Local Snapshot

conversation_id
→ snapshot not found
→ HTTP 404

Authenticated but Unrecoverable Remote Thread

conversation_id
→ local snapshot restored
→ remote Gemini thread is stale/unrecoverable
→ gemini_webapi retries internally
→ APIError 1097
→ HTTP 410

New Conversation

no conversation_id
→ existing retry behavior
→ unchanged

Root Cause

gemini_webapi performs retries internally through the @running(retry=5) decorator used by the content generation path.

The retry loop occurs before the final APIError reaches the application layer, preventing recovered conversations from failing fast.

Current behavior is functionally correct but introduces:

  • Additional latency
  • Repeated requests to Gemini
  • Noisy logs
  • Unnecessary client reinitialization attempts

Goal

Investigate whether gemini_webapi already exposes, or should expose upstream, an official per-request retry control for:

  • generate_content()
  • send_message()

This would allow recovered conversation failures to fail faster without affecting normal conversation behavior.

Constraints

  • Do not change behavior for new Gemini conversations.
  • Do not globally disable retries.
  • Do not reduce retry protection for ordinary provider failures.
  • Avoid coupling production code to internal decorator implementation details.
  • Avoid relying on undocumented internal parameters such as current_retry.
  • Prefer an official/public API for per-request retry overrides.

Desired Outcome

One of the following:

Option A (Preferred)

gemini_webapi provides an official per-request retry override.

Example:

await session.send_message(
    prompt,
    max_retries=0,
)

or

await client.generate_content(
    prompt,
    retry=0,
)

allowing recovered conversations to fail fast while preserving default retry behavior elsewhere.

Option B

If no safe public mechanism exists, document the limitation and retain the current implementation:

conversation_id
→ restore snapshot
→ internal retries
→ APIError 1097
→ HTTP 410

Related Work

Recently completed behavior:

  • Missing local snapshots return HTTP 404.
  • Unauthenticated recovered conversations return HTTP 401.
  • Authenticated but unrecoverable remote Gemini threads return HTTP 410.
  • Error code classification has been centralized through UNRECOVERABLE_CONVERSATION_ERROR_CODES.

The remaining issue is retry latency and noisy logs before the final HTTP 410 response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions