Skip to content

repro: sync error recovery classification is inconsistent across wrappers and causes - #2725

Draft
dorianvp wants to merge 1 commit into
devfrom
repro/error-classification-mismatches
Draft

repro: sync error recovery classification is inconsistent across wrappers and causes#2725
dorianvp wants to merge 1 commit into
devfrom
repro/error-classification-mismatches

Conversation

@dorianvp

Copy link
Copy Markdown
Member

Summary

This PR reproduces the claim error-classification-mismatches. It adds nine unit tests to the existing #[cfg(test)] module in pepper-sync/src/error.rs (new submodule classification_mismatches). Each test encodes the proposed classification, and every one fails on the current code. This is a reproduction and not a fix. No non-test code is changed.

The sync-bench A/B rule was not run because the commit adds tests only.

Claims and code cites

  1. ServerError::FetcherDropped is classified recommend_same_server() == true (pepper-sync/src/error.rs:129) and MaybeRecoverableServer (pepper-sync/src/error.rs:199). Every site that raises it is map_err(|_| ServerError::FetcherDropped) on a local channel send or a dropped oneshot (pepper-sync/src/client.rs:107, 111, and the same pattern at every other request helper). The server is not involved, so retrying the same server cannot help. Defect of fact.
  2. ServerError::RequestFailed(_) is false (error.rs:133) and ServerUnavailable (error.rs:201) for every tonic::Status. DeadlineExceeded and Unavailable are transient and retry worthy on the same server, while Unauthenticated, InvalidArgument, and Unimplemented are not availability problems. The tonic::Code is carried in the variant and is never inspected. The granularity is a design judgement, and the tests encode one proposed mapping.
  3. SyncError::ScanError(_) maps to Abort (error.rs:174) even for ScanError::IncorrectTreeSize (error.rs:272) and ScanError::IncorrectTxid (error.rs:286), both of which describe data the server returned. Design judgement, though the existing ScanError::ServerError arm at error.rs:173 already treats server caused scan failures as server problems.
  4. SyncError::MempoolError(_) is true (error.rs:101) and MaybeRecoverableServer (error.rs:171), while the unwrapped ServerError::RequestFailed(_) it may contain is false and ServerUnavailable (error.rs:133, 201). client.rs:406 constructs exactly MempoolError::ServerError(ServerError::RequestFailed(e)). The same failure gets the opposite verdict depending on the wrapper. Defect of fact.
  5. Not covered by tests. client.rs:215 and client.rs:352 gate stream retries on e.message().contains("Unexpected EOF decoding stream."), and the retry loop exists only for get_subtree_roots and get_transparent_address_transactions. Noted for context.

Tests

All nine are in pepper-sync/src/error.rs, module tests::classification_mismatches. Each assertion has its own #[test] so the run shows which parts fail.

Test Claim Asserts
fetcher_dropped_is_a_local_failure_and_aborts 1 FetcherDropped.recovery_recommendation() == Abort
fetcher_dropped_does_not_recommend_the_same_server 1 !FetcherDropped.recommend_same_server()
request_failed_deadline_exceeded_retries_the_same_server 2 RequestFailed(deadline_exceeded) is MaybeRecoverableServer
request_failed_unavailable_retries_the_same_server 2 RequestFailed(unavailable) is MaybeRecoverableServer
request_failed_unauthenticated_is_not_server_unavailable 2 RequestFailed(unauthenticated) is not ServerUnavailable
scan_error_incorrect_tree_size_tries_another_server 3 SyncError::ScanError(IncorrectTreeSize) is ServerUnavailable
scan_error_incorrect_txid_tries_another_server 3 SyncError::ScanError(IncorrectTxid) is ServerUnavailable
mempool_wrapped_request_failed_matches_direct_request_failed 4 wrapped and direct RequestFailed give the same recovery_recommendation()
mempool_wrapped_request_failed_matches_direct_recommend_same_server 4 wrapped and direct RequestFailed give the same recommend_same_server()

Observed output

Command: cargo test -p pepper-sync --lib error::tests::classification_mismatches

---- fetcher_dropped_is_a_local_failure_and_aborts ----
assertion `left == right` failed
  left: MaybeRecoverableServer
 right: Abort
---- fetcher_dropped_does_not_recommend_the_same_server ----
assertion failed: !ServerError::FetcherDropped.recommend_same_server()
---- request_failed_deadline_exceeded_retries_the_same_server ----
  left: ServerUnavailable
 right: MaybeRecoverableServer
---- request_failed_unavailable_retries_the_same_server ----
  left: ServerUnavailable
 right: MaybeRecoverableServer
---- request_failed_unauthenticated_is_not_server_unavailable ----
assertion `left != right` failed
  left: ServerUnavailable
 right: ServerUnavailable
---- scan_error_incorrect_tree_size_tries_another_server ----
  left: Abort
 right: ServerUnavailable
---- scan_error_incorrect_txid_tries_another_server ----
  left: Abort
 right: ServerUnavailable
---- mempool_wrapped_request_failed_matches_direct_request_failed ----
  left: MaybeRecoverableServer
 right: ServerUnavailable
---- mempool_wrapped_request_failed_matches_direct_recommend_same_server ----
  left: true
 right: false

test result: FAILED. 0 passed; 9 failed; 0 ignored; 0 measured; 111 filtered out

Note on existing tests

The existing tests recovery_recommendation::retry_same_server::fetcher_dropped and recovery_recommendation::try_different_server::request_failed assert the current behaviour, so a fix that adopts the proposed classification would need to update them as well.

🤖 Generated with Claude Code

…f and with the failure cause

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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