Skip to content

fix(provider): surface structured HTTP errors#172

Merged
omarluq merged 2 commits into
mainfrom
fix/provider-structured-http-errors
Jun 24, 2026
Merged

fix(provider): surface structured HTTP errors#172
omarluq merged 2 commits into
mainfrom
fix/provider-structured-http-errors

Conversation

@omarluq

@omarluq omarluq commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • add typed provider status errors with parsed provider details and safe body previews
  • attach typed request-shape diagnostics for failed provider HTTP responses
  • include structured provider error details in lifecycle payloads while preserving existing error strings
  • update retry/status handling to use typed provider errors

Validation

  • mise exec -- go test ./internal/provider ./internal/assistant/lifecyclepayload
  • mise exec -- golangci-lint run ./internal/provider ./internal/assistant/lifecyclepayload
  • mise exec -- go test ./...
  • mise exec -- task build
  • mise exec -- task ci

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

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 Plus

Run ID: 37fc467c-2a24-4b91-aca7-d4d7fdf8b2da

📥 Commits

Reviewing files that changed from the base of the PR and between 8f9646c and a2a059c.

📒 Files selected for processing (2)
  • internal/provider/request_shape.go
  • internal/provider/request_shape_internal_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/provider/request_shape.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Enhanced provider error diagnostics with structured details (message, type, code, param) plus request context.
    • Added outbound request-shape metadata to enrich troubleshooting output.
  • Bug Fixes
    • Improved retry logic to reliably prioritize provider status errors.
    • Standardized tools/input/reasoning payload keys and reasoning item detection across formats.
    • Added bounded, UTF-8-safe error body previews with truncated indicators.
  • Tests
    • Expanded coverage for structured error fields, request-shape behavior, and preview truncation.

Walkthrough

The PR adds typed provider error parsing and request-shape metadata, threads request-shape context into HTTP error construction, updates provider payload keys to shared constants, and merges structured provider diagnostics into lifecycle payloads and retry handling. Tests were expanded for the new error fields and payload shapes.

Changes

Structured Provider Error Model and Lifecycle Integration

Layer / File(s) Summary
RequestShape metadata and shared JSON keys
internal/provider/client.go, internal/provider/request_shape.go, internal/provider/request_shape_internal_test.go
Adds shared provider JSON key constants and introduces RequestShape with derived counts, flags, sorted keys, byte size, and payload emission rules.
StatusError and structured error parsing
internal/provider/errors.go, internal/provider/errors_internal_test.go
Replaces flat provider status error handling with typed StatusError and ErrorDetails, adds multi-shape JSON parsing, bounded UTF-8-safe body previews, and string-only helper logic.
Provider payload keys and stream error wiring
internal/provider/http.go, internal/provider/anthropic.go, internal/provider/openai_chat.go, internal/provider/openai_responses.go, internal/provider/openai_responses_sse.go, internal/provider/openai_responses_internal_test.go
Passes request-shape context into provider status errors and updates Anthropic, OpenAI chat, OpenAI responses, and SSE error handling to use shared JSON keys and normalized string extraction.
Lifecycle error detail bridge and retry classification
internal/assistant/lifecyclepayload/provider_error_details.go, internal/assistant/lifecyclepayload/lifecyclepayload.go, internal/assistant/retry.go, internal/assistant/lifecyclepayload/lifecyclepayload_test.go, internal/assistant/lifecyclepayload/behavior_test.go
Adds ProviderErrorDetails extraction, merges provider diagnostics into lifecycle payloads, and updates retry status detection to recognize provider StatusError values directly.

Sequence Diagram(s)

sequenceDiagram
  participant Stream as requestProviderStream
  participant Shape as providerRequestShape
  participant StatusErr as providerStatusError
  participant Parser as providerStatusError body parsing
  participant Retry as providerErrorStatus
  participant Bridge as ProviderErrorDetails
  participant Payload as ProviderErrorPayload

  Stream->>Shape: build RequestShape from payload
  Stream->>StatusErr: status, content, RequestShape
  StatusErr->>Parser: parse response body bytes
  Parser-->>StatusErr: StatusError with ErrorDetails
  StatusErr-->>Stream: non-2xx error

  Retry->>Retry: errors.As(err, *provider.StatusError)
  Retry-->>Retry: return status or fall back to oops context

  Bridge->>Bridge: inspect providerErr.Err
  Bridge-->>Payload: merge provider diagnostics into payload
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • omarluq/librecode#102: Touches the same internal/assistant/lifecyclepayload area and is directly connected to the lifecycle payload/error-detail code paths extended here.

Poem

🐇 Hop hop, the errors now stand in line,
With shapes and details that read just fine.
The payload keys all found their home,
And retries know which status to comb.
A rabbit cheers with twitchy nose—
Structured paths in tidy rows!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding structured HTTP error handling for provider responses.
Description check ✅ Passed The description is directly related to the changeset and accurately summarizes the new error handling and diagnostics.
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/provider-structured-http-errors

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

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.41065% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.96%. Comparing base (9006349) to head (a2a059c).

Files with missing lines Patch % Lines
...sistant/lifecyclepayload/provider_error_details.go 52.63% 17 Missing and 1 partial ⚠️
internal/provider/errors.go 87.76% 12 Missing and 5 partials ⚠️
internal/provider/request_shape.go 94.11% 2 Missing and 2 partials ⚠️
internal/assistant/retry.go 33.33% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #172      +/-   ##
==========================================
- Coverage   82.97%   82.96%   -0.01%     
==========================================
  Files         285      287       +2     
  Lines       22753    22977     +224     
==========================================
+ Hits        18879    19064     +185     
- Misses       2735     2769      +34     
- Partials     1139     1144       +5     
Flag Coverage Δ
unittests 82.96% <84.41%> (-0.01%) ⬇️

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

☔ View full report in Codecov by Harness.
📢 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/assistant/lifecyclepayload/lifecyclepayload_test.go (1)

132-156: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the *provider.StatusError path in this payload test too.

This case only exercises the oops fallback, but ProviderErrorDetails now prefers errors.As(..., *provider.StatusError). Adding a typed-error row here would lock down the new primary branch and catch lifecycle payload regressions earlier.

As per coding guidelines, **/*_test.go: Prefer table-driven tests for core behavior and regression tests for terminal rendering bugs in Go.

🤖 Prompt for 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.

In `@internal/assistant/lifecyclepayload/lifecyclepayload_test.go` around lines
132 - 156, The ProviderErrorPayload test currently only covers the oops fallback
path, but ProviderErrorDetails now primarily uses errors.As to match
*provider.StatusError. Update lifecyclepayload_test.go to add a table-driven
case in this test (or an adjacent one) that constructs a typed
provider.StatusError and verifies the same payload fields, so the new preferred
branch is exercised and regressions in ProviderErrorPayload/ProviderErrorDetails
are caught.

Source: Coding guidelines

🤖 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/provider/request_shape.go`:
- Around line 33-40: The request-shape detection in providerPayloadShape /
RequestShape should not infer Has* flags from raw JSON length, because non-empty
falsey values like false, empty string, empty array, or empty object are being
marked true. Update the logic that sets the HasParallelToolCalls,
HasPromptCacheKey, HasInclude, and HasReasoning flags to inspect the decoded
JSON value or token type rather than json.RawMessage length so the diagnostics
reflect the actual request content.

---

Nitpick comments:
In `@internal/assistant/lifecyclepayload/lifecyclepayload_test.go`:
- Around line 132-156: The ProviderErrorPayload test currently only covers the
oops fallback path, but ProviderErrorDetails now primarily uses errors.As to
match *provider.StatusError. Update lifecyclepayload_test.go to add a
table-driven case in this test (or an adjacent one) that constructs a typed
provider.StatusError and verifies the same payload fields, so the new preferred
branch is exercised and regressions in ProviderErrorPayload/ProviderErrorDetails
are caught.
🪄 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 Plus

Run ID: a1648b54-feeb-4385-90ab-33caa8fa8b67

📥 Commits

Reviewing files that changed from the base of the PR and between e8075e8 and 9b671dd.

📒 Files selected for processing (16)
  • internal/assistant/lifecyclepayload/behavior_test.go
  • internal/assistant/lifecyclepayload/lifecyclepayload.go
  • internal/assistant/lifecyclepayload/lifecyclepayload_test.go
  • internal/assistant/lifecyclepayload/provider_error_details.go
  • internal/assistant/retry.go
  • internal/provider/anthropic.go
  • internal/provider/client.go
  • internal/provider/errors.go
  • internal/provider/errors_internal_test.go
  • internal/provider/http.go
  • internal/provider/openai_chat.go
  • internal/provider/openai_responses.go
  • internal/provider/openai_responses_internal_test.go
  • internal/provider/openai_responses_sse.go
  • internal/provider/request_shape.go
  • internal/provider/request_shape_internal_test.go

Comment thread internal/provider/request_shape.go Outdated
@omarluq omarluq force-pushed the fix/provider-structured-http-errors branch from 9b671dd to 8f9646c Compare June 24, 2026 14:48
@sonarqubecloud

Copy link
Copy Markdown

@omarluq omarluq merged commit 8a30639 into main Jun 24, 2026
16 checks passed
@omarluq omarluq deleted the fix/provider-structured-http-errors branch June 24, 2026 15:27
@sonarqubecloud

Copy link
Copy Markdown

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.

1 participant