Skip to content

fix(kosong): classify base openai.APIError as retryable for streaming disconnections#1800

Merged
RealKai42 merged 4 commits intomainfrom
kaiyi/kathmandu-v1
Apr 9, 2026
Merged

fix(kosong): classify base openai.APIError as retryable for streaming disconnections#1800
RealKai42 merged 4 commits intomainfrom
kaiyi/kathmandu-v1

Conversation

@RealKai42
Copy link
Copy Markdown
Collaborator

@RealKai42 RealKai42 commented Apr 8, 2026

Summary

  • When the OpenAI SDK encounters a mid-stream transport failure, it raises the base openai.APIError (not APIConnectionError). The existing convert_error() did not handle this case — the error fell through to a generic ChatProviderError, bypassing both _run_with_connection_recovery and tenacity retry logic, causing an unrecoverable crash.
  • Added a guarded case openai.APIError() branch with dual guards (type(error) is openai.APIError + error.body is None) that heuristically maps transport-layer errors to the appropriate retryable error type based on message content.
  • SSE semantic errors (with body) and APIResponseValidationError subclasses are explicitly excluded from the heuristic classification.

Test plan

  • 13 parametrized unit tests covering network/timeout pattern matching, negative cases (bare "reset"/"closed"), and timeout-over-network priority
  • 2 safety guard tests: SSE error with body skips heuristic; APIResponseValidationError falls through
  • 1 subclass priority regression test
  • 1 streaming integration test: mock mid-flight APIError("Network connection lost.")APIConnectionError
  • make check-kosong passes (0 new diagnostics)
  • Full kosong test suite: 69 passed

Open with Devin

… disconnections

When the OpenAI SDK encounters a mid-stream transport failure it raises
the base `openai.APIError` instead of `APIConnectionError`. The existing
`convert_error()` did not handle this case, causing the error to become a
generic `ChatProviderError` that bypasses both `_run_with_connection_recovery`
and tenacity retry logic — resulting in an unrecoverable crash.

Add a guarded `case openai.APIError()` branch that heuristically maps
transport-layer errors (body=None, exact APIError type) to the appropriate
retryable error type based on the error message content.
Copilot AI review requested due to automatic review settings April 8, 2026 12:31
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an unrecoverable crash in the Kosong OpenAI integration when the OpenAI SDK raises a base openai.APIError during mid-stream transport failures (notably streaming disconnections), by classifying those base errors as retryable so existing recovery/retry logic can run.

Changes:

  • Extend convert_error() to detect exact openai.APIError instances with body is None and heuristically map them to APIConnectionError / APITimeoutError.
  • Add unit + integration tests covering the new base-APIError classification behavior and guardrails (body-present SSE errors and validation errors should not be reclassified).
  • Document the fix in package and CLI release notes / changelogs.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/kosong/src/kosong/chat_provider/openai_common.py Adds guarded base openai.APIError handling and message-based heuristic classification for retryability.
packages/kosong/tests/test_openai_common.py Adds parametrized unit tests and a streaming integration test to prevent regression.
packages/kosong/CHANGELOG.md Notes the Kosong package-level fix in Unreleased.
CHANGELOG.md Notes the CLI-level fix in Unreleased.
docs/en/release-notes/changelog.md Adds the Unreleased release-note entry in English.
docs/zh/release-notes/changelog.md Adds the Unreleased release-note entry in Chinese.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Signed-off-by: Kai <me@kaiyi.cool>
Signed-off-by: Kai <me@kaiyi.cool>
@RealKai42 RealKai42 merged commit 9d77e7e into main Apr 9, 2026
15 of 18 checks passed
@RealKai42 RealKai42 deleted the kaiyi/kathmandu-v1 branch April 9, 2026 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants