fix(perps): historical-candle cancellation handling #28953
Conversation
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Add isAbortError() utility to detect expected cancellation errors from AbortController during navigation/view teardown. Guard all 3 catch blocks (HyperLiquidClientService, MarketDataService, CandleStreamChannel) to skip Sentry logging for abort errors while preserving real error reporting.
Worker reportReport: TAT-2971 — Fix perps historical-candle cancellation handlingSummaryAbortErrors from candle fetch cancellations (during normal navigation/view teardown) were treated as real errors and logged to Sentry at 3 service layers. Added Root cause
Reproduction commitSHA: Changes
Test planAutomated
Manual (Gherkin)Evidence
TicketWorkflow Diagram (Mermaid) |
…-switch screenshot
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection: SmokePerps is selected as the primary tag since all changes are in Perps controllers and candle streaming infrastructure. Per the SmokePerps tag description, SmokeWalletPlatform must also be selected (Perps is a section inside the Trending tab) and SmokeConfirmations must also be selected (Add Funds deposits are on-chain transactions). The agentic flow JSON files (candle-rapid-switch.json, market-visit.json) are scripted test flows for the agentic testing framework, not Detox E2E tests, so they don't affect tag selection. No other areas (accounts, network, identity, swaps, ramps, etc.) are affected by these changes. Performance Test Selection: |
|
✅ E2E Fixture Validation — Schema is up to date |
|



Description
AbortErrors from candle fetch cancellations during normal navigation/view teardown were treated as real errors and logged to Sentry at 3 service layers. Added
isAbortError()utility and abort guards at all 3 catch blocks (HyperLiquidClientService,MarketDataService,CandleStreamChannel) to suppress expected cancellation noise while preserving real error reporting.Also adds two reusable agentic flows:
perps/candle-rapid-switch— cycles through BTC→ETH→SOL→HYPE→BTC→ETH and asserts no candle rate-limit or abort errors appear in logs. Reusable regression check for any PR touching the candle fetch path.perps/market-visit— single-market atom (open detail → wait → back). Building block for composing multi-market navigation sequences.Changelog
CHANGELOG entry: Fixed noisy Sentry error reports from expected candle fetch cancellations during navigation
Related issues
Fixes: TAT-2971
Manual testing steps
Screenshots/Recordings
Before
After
after-rapid-switch-validation.mp4
Pre-merge author checklist
Pre-merge reviewer checklist
Validation Recipe
recipe.json
{ "pr": "28953", "title": "Verify candle abort errors are not logged to Sentry", "jira": "TAT-2971", "acceptance_criteria": [ "Expected candle-request cancellations (AbortError) are not reported as errors to Sentry/Logger", "Real candle fetch failures still log/report normally to Sentry/Logger", "No new TypeScript errors introduced" ], "validate": { "static": ["yarn lint:tsc"], "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "setup-nav-market", "nodes": { "setup-nav-market": { "action": "call", "ref": "perps/market-discovery", "params": { "symbol": "BTC" }, "next": "ac2-wait-candles" }, "ac2-wait-candles": { "action": "wait_for", "expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(ms){var m=ms.find(function(x){return x.symbol==='BTC'});return JSON.stringify({found:!!m,price:m?m.price:'0'})})", "assert": { "operator": "not_null", "field": "price" }, "timeout_ms": 15000, "next": "ac2-screenshot-candles" }, "ac2-screenshot-candles": { "action": "screenshot", "filename": "evidence-ac2-candles-loaded.png", "next": "setup-nav-away" }, "setup-nav-away": { "action": "navigate", "target": "Wallet", "next": "setup-wait-teardown" }, "setup-wait-teardown": { "action": "wait", "ms": 500, "next": "ac1-log-check" }, "ac1-log-check": { "action": "log_watch", "window_seconds": 10, "must_not_appear": ["BUG_MARKER: abort error logged to Sentry"], "watch_for": ["CandleStreamChannel"], "next": "ac1-screenshot-clean-logs" }, "ac1-screenshot-clean-logs": { "action": "screenshot", "filename": "evidence-ac1-no-abort-noise.png", "next": "ac3-rapid-switch" }, "ac3-rapid-switch": { "action": "call", "ref": "perps/candle-rapid-switch", "params": { "screenshot_filename": "evidence-ac3-rapid-switch-chart.png" }, "next": "done" }, "done": { "action": "end", "status": "pass" } } } } }Recipe Workflow
workflow graph
graph TD setup-nav-market["setup-nav-market<br/>call: perps/market-discovery"] --> ac2-wait-candles ac2-wait-candles["ac2-wait-candles<br/>wait_for: BTC price"] --> ac2-screenshot-candles ac2-screenshot-candles["ac2-screenshot-candles<br/>screenshot"] --> setup-nav-away setup-nav-away["setup-nav-away<br/>navigate: Wallet"] --> setup-wait-teardown setup-wait-teardown["setup-wait-teardown<br/>wait 500ms"] --> ac1-log-check ac1-log-check["ac1-log-check<br/>log_watch: no abort noise"] --> ac1-screenshot-clean-logs ac1-screenshot-clean-logs["ac1-screenshot-clean-logs<br/>screenshot"] --> ac3-rapid-switch ac3-rapid-switch["ac3-rapid-switch<br/>call: perps/candle-rapid-switch<br/>BTC→ETH→SOL→HYPE→BTC→ETH"] --> done done["done<br/>end: pass"]