Skip to content

fix(assistant): retry provider timeouts#46

Merged
omarluq merged 2 commits into
mainfrom
fix/retry-provider-timeouts
May 24, 2026
Merged

fix(assistant): retry provider timeouts#46
omarluq merged 2 commits into
mainfrom
fix/retry-provider-timeouts

Conversation

@omarluq
Copy link
Copy Markdown
Owner

@omarluq omarluq commented May 24, 2026

Summary

  • retry provider/client deadline timeouts that look like upstream HTTP timeouts
  • preserve partial streamed progress in the UI when provider attempts ultimately fail
  • add regression coverage for timeout classification and failed streamed progress

Validation

  • mise exec -- go test ./internal/assistant ./internal/terminal
  • mise exec -- task ci

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2d8d7f3a-a03c-4a2b-8ff7-7eb468c3feb8

📥 Commits

Reviewing files that changed from the base of the PR and between 9ed22cb and 1783deb.

📒 Files selected for processing (2)
  • internal/assistant/retry.go
  • internal/assistant/retry_timeout_test.go

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Refined retry behavior for timeout/deadline errors to retry only when messages indicate provider-side timeouts.
    • Preserve and restore streamed prompt progress on failures so partial content remains visible.
    • Improve error returned when persisting partial progress fails for clearer diagnostics.
  • Tests

    • Added tests covering deadline-exceeded retry behavior and visibility of streamed progress when prompts fail.

Walkthrough

The PR refines retry classification for deadline-exceeded errors, changes partial-prompt error propagation to return a distinct persistence-failure error when saving partial progress fails, and preserves streamed message progress on prompt cancellation/failure by snapshotting and selectively restoring streamed blocks.

Changes

Error handling and retry classification

Layer / File(s) Summary
Deadline-exceeded retry classification
internal/assistant/retry.go, internal/assistant/retry_timeout_test.go
ShouldRetryModelError no longer treats context.DeadlineExceeded as immediately non-retryable; it lowercases the error message, applies nonRetryableProviderMessage, and delegates DeadlineExceeded to retryableDeadlineExceeded, which returns retryable only for specific timeout/HTTP-stream phrases. Tests cover provider timeout vs. caller-deadline cases.

Partial progress error propagation

Layer / File(s) Summary
Partial progress error propagation
internal/assistant/runtime.go, internal/assistant/runtime_test.go
Removes errors.Join usage; respondWithPartialProgress returns a dedicated persistence-failure error when saving partial progress fails or otherwise returns the original prompt error. Test now asserts the exact error string.

Streaming block preservation on error

Layer / File(s) Summary
Streaming block restoration
internal/terminal/async_events.go, internal/terminal/render_test.go
Captures app.streamingBlocks before resetting state and restores previously streamed assistant/tool/custom/thinking blocks via applyFailedPromptStreamedBlocks, skipping user/branch/compaction roles. Tests verify partial progress remains visible and app.streamingBlocks is cleared.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • omarluq/librecode#42: Modifies internal/assistant/retry.go retry classification and internal/assistant/runtime.go partial-progress persistence, overlapping with deadline-exceeded and error-join behavior changes.

Poem

A deadline tapped at the burrow door,
I sniffed the message, then checked once more.
Some timeouts bounce back to try again,
While caller clocks quietly remain.
Streams keep their footprints, saved by my paw — progress stays when the prompt meets a flaw. 🐰

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(assistant): retry provider timeouts' directly reflects the main objective of the PR: to retry provider timeout errors. It is concise and accurately summarizes the primary change.
Description check ✅ Passed The description clearly relates to the changeset, outlining three specific objectives: retrying provider timeouts, preserving streamed progress on failures, and adding test coverage. These align with the file changes across retry logic, runtime handling, and new tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/retry-provider-timeouts

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 24, 2026

Codecov Report

❌ Patch coverage is 62.50000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.72%. Comparing base (f64fe71) to head (1783deb).

Files with missing lines Patch % Lines
internal/terminal/async_events.go 50.00% 6 Missing and 1 partial ⚠️
internal/assistant/runtime.go 16.66% 4 Missing and 1 partial ⚠️

❌ Your patch status has failed because the patch coverage (62.50%) is below the target coverage (70.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #46      +/-   ##
==========================================
+ Coverage   60.68%   60.72%   +0.03%     
==========================================
  Files         172      172              
  Lines       16901    16928      +27     
==========================================
+ Hits        10257    10280      +23     
  Misses       5624     5624              
- Partials     1020     1024       +4     
Flag Coverage Δ
unittests 60.72% <62.50%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/assistant/retry.go`:
- Around line 119-122: The function retryableDeadlineExceeded is using a
call-site label ("request provider response") as a retry signal which causes
wrapped caller deadlines to be treated as provider retries; remove the check for
"request provider response" from retryableDeadlineExceeded and instead rely only
on provider-specific indicators (e.g. "client.timeout exceeded" and "awaiting
headers") or, better, update retryableDeadlineExceeded to inspect/unwrap the
provided error (using errors.Is/errors.As) to detect provider-specific error
types rather than matching call-site messages; adjust the function signature and
callers as needed to use the unwrapped error checks and add a clarifying comment
in retryableDeadlineExceeded about avoiding call-site labels as retry signals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6a816dde-a03f-4001-993b-17ac62483e09

📥 Commits

Reviewing files that changed from the base of the PR and between f64fe71 and 9ed22cb.

📒 Files selected for processing (6)
  • internal/assistant/retry.go
  • internal/assistant/retry_timeout_test.go
  • internal/assistant/runtime.go
  • internal/assistant/runtime_test.go
  • internal/terminal/async_events.go
  • internal/terminal/render_test.go

Comment thread internal/assistant/retry.go Outdated
@sonarqubecloud
Copy link
Copy Markdown

@omarluq omarluq merged commit 1819fcf into main May 24, 2026
13 checks passed
@omarluq omarluq deleted the fix/retry-provider-timeouts branch May 24, 2026 20:38
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