Skip to content

Propagate subgraph errors instead of silently swallowing them#2494

Merged
findolor merged 2 commits intomainfrom
2026-03-02-subgraph-error-propagation-v1
Apr 13, 2026
Merged

Propagate subgraph errors instead of silently swallowing them#2494
findolor merged 2 commits intomainfrom
2026-03-02-subgraph-error-propagation-v1

Conversation

@findolor
Copy link
Copy Markdown
Collaborator

@findolor findolor commented Mar 6, 2026

Motivation

The MultiOrderbookSubgraphClient methods (orders_list, vaults_list, tokens_list) were silently
discarding subgraph errors via filter_map(Result::ok). This meant HTTP errors (e.g. 429 rate limits,
500s) were invisible to callers — queries would return empty results with no indication of failure.

Solution

  • Changed orders_list, vaults_list, and tokens_list to return Result types, propagating
    OrderbookSubgraphClientError to callers.
  • Errors are only surfaced when all subgraphs fail or return no data — if at least one subgraph
    succeeds with results, the error is tolerated and partial results are returned.
  • Added CynicClientError::HttpError variant to capture non-2xx HTTP responses with status code and body.
  • Updated callers in orders.rs and vaults.rs to propagate errors with ?.
  • Added tests for HTTP 429 error propagation and partial-success scenarios.

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • Bug Fixes

    • Subgraph queries (orders, vaults, tokens) now propagate failures instead of continuing with invalid results.
    • Multi-subgraph queries surface errors when all subgraphs fail while still returning partial successes when at least one succeeds.
    • HTTP errors now include status codes and response bodies for clearer diagnostics.
  • Tests

    • Added/updated tests covering HTTP error and rate-limiting scenarios.

@findolor
Copy link
Copy Markdown
Collaborator Author

#2497

After this PR merges we need to add this to the list of propagated errors.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: converting silent error discarding to explicit error propagation in subgraph operations.

✏️ 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 2026-03-02-subgraph-error-propagation-v1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
crates/subgraph/src/multi_orderbook_client.rs (1)

58-70: Factor the partial-success fold into one helper.

The same all_items + last_error reduction now lives in three methods, but only orders_list has the full new 429-specific regression coverage. A small shared helper and shared test matrix would make future behavior changes much less likely to drift between orders, vaults, and tokens.

Based on learnings, "if error propagation behavior should change, implement the change consistently across all related methods in a single PR."

Also applies to: 127-139, 165-177

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/subgraph/src/multi_orderbook_client.rs` around lines 58 - 70, Factor
the repeated reduction into a single helper (e.g., merge_partial_results or
collect_partial_items) that is generic over item type and error type and
reproduces the exact behavior: iterate results, extend a single Vec with all
Ok(items), track the most recent Err as last_error, and if the final Vec is
empty return Err(last_error) else return Ok(all_items). Replace the duplicated
fold in orders_list and the other two methods (the other blocks at the ranges
referenced) to call this helper; ensure the helper's signature fits the methods
(consume the iterator of Result<Vec<T>, E> and return Result<Vec<T>, E>) and
update tests to call the shared test matrix so the 429-specific behavior remains
covered consistently across all three call sites.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/common/src/raindex_client/vaults.rs`:
- Line 1491: The subgraph call currently uses the fall-through "?.await" which
lets subgraph errors override successful local-db results in get_vaults() and
get_all_vault_tokens(); change the logic so that when
is_chain_supported_local_db() is true and local DB produced results, those
results are returned without being dropped by a subsequent subgraph error
(remove the direct ?.await propagation on the subgraph call, capture the
subgraph Result, and only propagate an error if all sources are empty), and add
a regression test exercising a mixed local_db + subgraph scenario where the
subgraph is rate-limited/down but local DB has items to ensure local results are
preserved.

---

Nitpick comments:
In `@crates/subgraph/src/multi_orderbook_client.rs`:
- Around line 58-70: Factor the repeated reduction into a single helper (e.g.,
merge_partial_results or collect_partial_items) that is generic over item type
and error type and reproduces the exact behavior: iterate results, extend a
single Vec with all Ok(items), track the most recent Err as last_error, and if
the final Vec is empty return Err(last_error) else return Ok(all_items). Replace
the duplicated fold in orders_list and the other two methods (the other blocks
at the ranges referenced) to call this helper; ensure the helper's signature
fits the methods (consume the iterator of Result<Vec<T>, E> and return
Result<Vec<T>, E>) and update tests to call the shared test matrix so the
429-specific behavior remains covered consistently across all three call sites.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3e9477b-1039-4dc1-bf74-56949fc6fbd5

📥 Commits

Reviewing files that changed from the base of the PR and between e686b4d and fcf90e6.

📒 Files selected for processing (5)
  • crates/common/src/raindex_client/orders.rs
  • crates/common/src/raindex_client/vaults.rs
  • crates/subgraph/src/cynic_client.rs
  • crates/subgraph/src/multi_orderbook_client.rs
  • crates/subgraph/src/vault_balance_changes_query.rs

Comment thread crates/common/src/raindex_client/vaults.rs
@findolor findolor requested a review from JuaniRios April 10, 2026 11:35
Copy link
Copy Markdown
Collaborator Author

findolor commented Apr 13, 2026

Merge activity

  • Apr 13, 7:12 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 13, 7:13 AM UTC: Graphite rebased this pull request as part of a merge.
  • Apr 13, 7:35 AM UTC: Graphite couldn't merge this PR because it was not satisfying all requirements (Failed CI: 'standard-tests (ubuntu-latest, rainix-sol-test)').
  • Apr 13, 8:33 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 13, 8:33 AM UTC: @findolor merged this pull request with Graphite.

Add HTTP status checking to CynicClient, change multi-orderbook client
methods to return Result, and propagate errors to callers. When some
subgraphs succeed and others fail, return partial results; only error
when all subgraphs fail. Includes tests for rate-limiting (HTTP 429).
@findolor findolor force-pushed the 2026-03-02-subgraph-error-propagation-v1 branch from fcf90e6 to a59df5b Compare April 13, 2026 07:12
Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/subgraph/src/multi_orderbook_client.rs (1)

144-180: ⚠️ Potential issue | 🟡 Minor

Add tokens_list tests for new error semantics.

tokens_list now has propagation logic identical to orders/vaults, but this file doesn’t include equivalent tests for all-error and partial-success paths. Please add parity tests to lock behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/subgraph/src/multi_orderbook_client.rs` around lines 144 - 180, Add
unit tests covering the new error semantics in tokens_list: create two tests
mirroring the orders/vaults cases — one where all subgraph clients return errors
and tokens_list returns Err (propagating the last error from
get_orderbook_subgraph_client/tokens_list_all), and one partial-success case
where some subgraphs return tokens and others return errors and tokens_list
returns Ok with the combined SgErc20WithSubgraphName items; locate the test
helpers/mocks used by existing orders/vaults tests and reuse the same mocking
for get_orderbook_subgraph_client and tokens_list_all, assert returned Err for
the all-error test and assert combined Vec contents (including subgraph_name)
for the partial-success test.
🧹 Nitpick comments (1)
crates/subgraph/src/multi_orderbook_client.rs (1)

58-70: Extract duplicated aggregation block into a shared helper.

The same all_* + last_error merge logic is repeated three times. A generic helper would reduce drift risk and keep semantics aligned.

♻️ Proposed refactor
+    fn merge_subgraph_results<T>(
+        results: Vec<Result<Vec<T>, OrderbookSubgraphClientError>>,
+    ) -> Result<Vec<T>, OrderbookSubgraphClientError> {
+        let mut all_items = Vec::new();
+        let mut last_error = None;
+        for result in results {
+            match result {
+                Ok(items) => all_items.extend(items),
+                Err(e) => last_error = Some(e),
+            }
+        }
+        if all_items.is_empty() {
+            if let Some(e) = last_error {
+                return Err(e);
+            }
+        }
+        Ok(all_items)
+    }
-        let mut all_orders = Vec::new();
-        let mut last_error = None;
-        for result in results {
-            match result {
-                Ok(items) => all_orders.extend(items),
-                Err(e) => last_error = Some(e),
-            }
-        }
-        if all_orders.is_empty() {
-            if let Some(e) = last_error {
-                return Err(e);
-            }
-        }
+        let mut all_orders = Self::merge_subgraph_results(results)?;

Also applies to: 127-139, 165-177

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/subgraph/src/multi_orderbook_client.rs` around lines 58 - 70, Extract
the repeated aggregation logic that collects Ok(Vec<T>) into a single Vec and
returns the last Err if no items were collected into a generic helper like
merge_results<T, E>(results: impl IntoIterator<Item = Result<Vec<T>, E>>) ->
Result<Vec<T>, E>; replace the three in-place loops that use variables
all_orders / all_* , last_error and iterate over results with calls to this
helper (keeping the same semantics: extend on Ok, track last Err, and return Err
only if the final collected Vec is empty and an Err was seen). Update call sites
to import/use the helper and ensure its signature matches the error type used in
those callers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@crates/subgraph/src/multi_orderbook_client.rs`:
- Around line 144-180: Add unit tests covering the new error semantics in
tokens_list: create two tests mirroring the orders/vaults cases — one where all
subgraph clients return errors and tokens_list returns Err (propagating the last
error from get_orderbook_subgraph_client/tokens_list_all), and one
partial-success case where some subgraphs return tokens and others return errors
and tokens_list returns Ok with the combined SgErc20WithSubgraphName items;
locate the test helpers/mocks used by existing orders/vaults tests and reuse the
same mocking for get_orderbook_subgraph_client and tokens_list_all, assert
returned Err for the all-error test and assert combined Vec contents (including
subgraph_name) for the partial-success test.

---

Nitpick comments:
In `@crates/subgraph/src/multi_orderbook_client.rs`:
- Around line 58-70: Extract the repeated aggregation logic that collects
Ok(Vec<T>) into a single Vec and returns the last Err if no items were collected
into a generic helper like merge_results<T, E>(results: impl IntoIterator<Item =
Result<Vec<T>, E>>) -> Result<Vec<T>, E>; replace the three in-place loops that
use variables all_orders / all_* , last_error and iterate over results with
calls to this helper (keeping the same semantics: extend on Ok, track last Err,
and return Err only if the final collected Vec is empty and an Err was seen).
Update call sites to import/use the helper and ensure its signature matches the
error type used in those callers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a65841d9-d6d1-42a8-a5d0-1d94f6f0d488

📥 Commits

Reviewing files that changed from the base of the PR and between fcf90e6 and a59df5b.

📒 Files selected for processing (5)
  • crates/common/src/raindex_client/orders.rs
  • crates/common/src/raindex_client/vaults.rs
  • crates/subgraph/src/cynic_client.rs
  • crates/subgraph/src/multi_orderbook_client.rs
  • crates/subgraph/src/vault_balance_changes_query.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/common/src/raindex_client/orders.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/subgraph/src/vault_balance_changes_query.rs
  • crates/subgraph/src/cynic_client.rs
  • crates/common/src/raindex_client/vaults.rs

@findolor findolor merged commit c2cd933 into main Apr 13, 2026
27 of 28 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment:

S/M/L PR Classification Guidelines:

This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed.

Small (S)

Characteristics:

  • Simple bug fixes, typos, or minor refactoring
  • Single-purpose changes affecting 1-2 files
  • Documentation updates
  • Configuration tweaks
  • Changes that require minimal context to review

Review Effort: Would have taken 5-10 minutes

Examples:

  • Fix typo in variable name
  • Update README with new instructions
  • Adjust configuration values
  • Simple one-line bug fixes
  • Import statement cleanup

Medium (M)

Characteristics:

  • Feature additions or enhancements
  • Refactoring that touches multiple files but maintains existing behavior
  • Breaking changes with backward compatibility
  • Changes requiring some domain knowledge to review

Review Effort: Would have taken 15-30 minutes

Examples:

  • Add new feature or component
  • Refactor common utility functions
  • Update dependencies with minor breaking changes
  • Add new component with tests
  • Performance optimizations
  • More complex bug fixes

Large (L)

Characteristics:

  • Major feature implementations
  • Breaking changes or API redesigns
  • Complex refactoring across multiple modules
  • New architectural patterns or significant design changes
  • Changes requiring deep context and multiple review rounds

Review Effort: Would have taken 45+ minutes

Examples:

  • Complete new feature with frontend/backend changes
  • Protocol upgrades or breaking changes
  • Major architectural refactoring
  • Framework or technology upgrades

Additional Factors to Consider

When deciding between sizes, also consider:

  • Test coverage impact: More comprehensive test changes lean toward larger classification
  • Risk level: Changes to critical systems bump up a size category
  • Team familiarity: Novel patterns or technologies increase complexity

Notes:

  • the assessment must be for the totality of the PR, that means comparing the base branch to the last commit of the PR
  • the assessment output must be exactly one of: S, M or L (single-line comment) in format of: SIZE={S/M/L}
  • do not include any additional text, only the size classification
  • your assessment comment must not include tips or additional sections
  • do NOT tag me or anyone else on your comment

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

Tip

For best results, initiate chat on the files or code changes.

SIZE=M

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.

3 participants