Skip to content

fix(perps): historical-candle cancellation handling #28953

Merged
abretonc7s merged 5 commits into
mainfrom
fix/tat-2971-fix-perps-cancel-handling
Apr 17, 2026
Merged

fix(perps): historical-candle cancellation handling #28953
abretonc7s merged 5 commits into
mainfrom
fix/tat-2971-fix-perps-cancel-handling

Conversation

@abretonc7s

@abretonc7s abretonc7s commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

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

Feature: Candle fetch cancellation handling

  Scenario: user navigates away from market detail during candle load
    Given the user is on the Perps BTC market detail screen
    And candle data is loading via WebSocket

    When user navigates away from the market detail screen
    Then no AbortError is logged to Sentry
    And candle data loaded successfully before navigation

  Scenario: rapid market switching does not trigger rate-limit errors
    Given the user is on the Perps market list
    When user rapidly opens and closes BTC, ETH, SOL, HYPE, BTC, ETH in sequence
    Then all candle charts load successfully
    And no candleSnapshot or rate-limit errors appear in logs

  Scenario: real candle fetch failure still reports
    Given the user is on the Perps BTC market detail screen
    When a real network error occurs during candle fetch
    Then the error is logged to Sentry normally

Screenshots/Recordings

Before

After

after-rapid-switch-validation.mp4

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

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"]
Loading

@abretonc7s abretonc7s added DO-NOT-MERGE Pull requests that should not be merged agentic labels Apr 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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.

@metamaskbotv2 metamaskbotv2 Bot added the team-perps Perps team label Apr 16, 2026
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.
@abretonc7s

abretonc7s commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author
Run Duration Model Nudges Grade Cost
e56fce9b ? opus 0 7/10 (high) $unknown
Worker report

Report: TAT-2971 — Fix perps historical-candle cancellation handling

Summary

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 to suppress expected cancellation noise while preserving real error reporting.

Root cause

HyperLiquidClientService.subscribeToCandles() (line 593) creates an AbortController whose signal is passed to fetchHistoricalCandles (line 609). On cleanup, abort() fires (line 755). The fetchHistoricalCandles catch block at line ~536 logs to Sentry BEFORE the caller's abort check at line 712-714 can suppress it. The error then propagates through MarketDataService.fetchHistoricalCandles (line ~782) and CandleStreamChannel.fetchHistoricalCandles (line ~537), each logging again — 3 Sentry reports for 1 expected cancellation.

Reproduction commit

SHA: 5c0a17f06d — added BUG_MARKER: abort error logged to Sentry DevLogger line in HyperLiquidClientService catch block. Metro log confirmed marker fired during candle teardown.

Changes

File Change
app/controllers/perps/utils/errorUtils.ts Added isAbortError() utility — detects AbortError by name or message pattern
app/controllers/perps/services/HyperLiquidClientService.ts Added abort guard in fetchHistoricalCandles catch — skips Sentry, re-throws
app/controllers/perps/services/MarketDataService.ts Wrapped Sentry logging + state update in !isAbortError() guard
app/components/UI/Perps/providers/channels/CandleStreamChannel.ts Added early return for abort errors before Logger.error
app/controllers/perps/index.ts Export isAbortError from utils barrel
app/controllers/perps/utils/errorUtils.test.ts New: 10 tests for isAbortError and ensureError
app/controllers/perps/services/MarketDataService.test.ts Added 2 tests: abort errors skip Sentry, real errors still log
app/components/UI/Perps/providers/channels/CandleStreamChannel.test.ts Added 1 test: abort errors skip Logger.error

Test plan

Automated

  • Unit tests: 13 new/modified tests across 3 files — all pass
  • Lint: yarn lint
  • TypeScript: yarn lint:tsc
  • Format: yarn format:check
  • Recipe: validate-recipe.sh exits 0 — navigates to BTC market, verifies candle data loads, navigates away (triggers teardown), asserts no BUG_MARKER in logs
  • Coverage: yarn coverage:analyze

Manual (Gherkin)

Given the user is on the Perps BTC market detail screen
And candle data is loading via WebSocket
When the user navigates away from the market detail screen
Then no AbortError is logged to Sentry
And the candle data loaded successfully before navigation

Evidence

Artifact Description
before.mp4 Recipe run on pre-fix code
after.mp4 Recipe run on final fixed code
before-ac2-candles-loaded.png BTC candle chart before fix
after-ac2-candles-loaded.png BTC candle chart after fix
before-ac1-no-abort-noise.png Log state before fix
after-ac1-no-abort-noise.png Log state after fix
recipe-coverage.md 3/3 ACs PROVEN

Ticket

TAT-2971

Workflow Diagram (Mermaid)

@abretonc7s abretonc7s marked this pull request as ready for review April 16, 2026 22:32
@abretonc7s abretonc7s requested a review from a team as a code owner April 16, 2026 22:32
@github-actions github-actions Bot added the risk-low Low testing needed · Low bug introduction risk label Apr 17, 2026
@github-actions github-actions Bot added risk-low Low testing needed · Low bug introduction risk and removed risk-low Low testing needed · Low bug introduction risk labels Apr 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePerps, SmokeWalletPlatform, SmokeConfirmations
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 92%
click to see 🤖 AI reasoning details

E2E Test Selection:
All changes are scoped entirely to the Perps feature. The PR introduces a new isAbortError() utility function and uses it across three Perps-related files (HyperLiquidClientService, MarketDataService, CandleStreamChannel) to suppress noisy Sentry error reports for expected AbortController cancellations that occur during normal navigation/view teardown. The change also skips unnecessary state updates when abort errors occur. This is a targeted error-handling improvement with no impact on other wallet features.

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:
The changes are purely error-handling improvements that suppress Sentry logging for expected AbortController cancellations. While this could marginally reduce unnecessary state updates during rapid market switching, it does not affect core rendering performance, data loading pipelines, or any performance-critical paths. No performance tests are warranted.

View GitHub Actions results

@abretonc7s abretonc7s changed the title fix(perps): Fix perps historical-candle cancellation handling fix(perps): historical-candle cancellation handling Apr 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
12 value mismatches detected (expected — fixture represents an existing user).
View details

@sonarqubecloud

Copy link
Copy Markdown

@abretonc7s abretonc7s added this pull request to the merge queue Apr 17, 2026
Merged via the queue into main with commit 5937989 Apr 17, 2026
120 of 121 checks passed
@abretonc7s abretonc7s deleted the fix/tat-2971-fix-perps-cancel-handling branch April 17, 2026 12:42
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 17, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.75.0 Issue or pull request that will be included in release 7.75.0 label Apr 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

agentic DO-NOT-MERGE Pull requests that should not be merged release-7.75.0 Issue or pull request that will be included in release 7.75.0 risk-low Low testing needed · Low bug introduction risk size-M team-perps Perps team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants