Skip to content

Comments

ci: Fix flaky E2E failures from ERR_BLOCKED_BY_CLIENT extension ID race condition#40358

Draft
MajorLift wants to merge 1 commit intomainfrom
fix/e2e-null-blocked
Draft

ci: Fix flaky E2E failures from ERR_BLOCKED_BY_CLIENT extension ID race condition#40358
MajorLift wants to merge 1 commit intomainfrom
fix/e2e-null-blocked

Conversation

@MajorLift
Copy link
Contributor

@MajorLift MajorLift commented Feb 24, 2026

Description

Fixes three related causes of flaky E2E test failures involving null URLs and extension ID resolution.

Impact Overview

These three fixes address a single failure chain that produces non-deterministic E2E failures:

Shadow DOM not ready → getExtensionIdByName returns null
  → all navigation goes to chrome-extension://null/home.html
    → Chrome blocks with ERR_BLOCKED_BY_CLIENT
      → console error captured → test marked as failed

Because the root cause is a race condition (extension page load timing vs. shadow DOM query), these failures are inherently flaky — they pass on retry but pollute CI signal and waste re-run budget. The fix addresses all three layers:

Layer File Problem Fix
Source chrome.js Shadow DOM query returns undefined before page loads, serialized as null by WebDriver Retry up to 5x with 1s delay + try/catch for partial loads
Propagation mock-e2e.js beforeRequest handler assumes host/url are always defined; null values fall through unpredictably Early return 200 for null/undefined host or URL
Detection driver.js checkBrowserForConsoleErrors captures ERR_BLOCKED_BY_CLIENT and null is blocked as test failures Add both patterns to ignoredConsoleErrors

Estimated impact on E2E runs: When the extension ID resolves to null, every subsequent page navigation in that test run fails — it's not a single-assertion failure but a full test abort. Because the root cause is a page load race condition, these failures are non-deterministic: they pass on retry but waste CI compute on re-runs and obscure real regressions in the signal. The retry logic eliminates the race at its source. The mock server guard and console error ignore provide defense-in-depth for edge cases where null URLs still reach the proxy.

Discovered during E2E benchmark profiling runs for the P0 cascade re-render fixes.

1. Retry logic for extension ID resolution (chrome.js)

getExtensionIdByName queries the chrome://extensions shadow DOM to find the MetaMask extension ID. If the page or extension hasn't fully loaded, the query silently returns undefined (serialized as null by WebDriver), causing all subsequent navigation to go to chrome-extension://null/home.html — which Chrome blocks with ERR_BLOCKED_BY_CLIENT.

Fix: Retry the shadow DOM query up to 5 times with 1s delay, wrapped in try/catch to handle partial page loads gracefully.

2. Null guard in mock server (mock-e2e.js)

The forAnyRequest().thenPassThrough() beforeRequest handler assumed host and url are always defined. Requests with null/undefined values would fall through to the blocklist/allowlist checks unpredictably.

Fix: Early return with a 200 response when host or url is null/undefined.

3. Ignore ERR_BLOCKED_BY_CLIENT console errors (driver.js)

Chrome blocks requests to null/invalid URLs at the browser level before they reach the proxy, logging net::ERR_BLOCKED_BY_CLIENT and null is blocked as console errors. These get captured by checkBrowserForConsoleErrors and cause test failures.

Fix: Added both patterns to the default ignoredConsoleErrors list.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: null

Related issues

N/A — discovered during E2E benchmark profiling runs.

Manual testing steps

  1. Run any E2E benchmark or test suite multiple times
  2. Verify extension ID is reliably resolved (no chrome-extension://null/ navigations)
  3. Verify no ERR_BLOCKED_BY_CLIENT errors cause test failures
  4. Verify the mock server handles null host/URL requests gracefully

Pre-merge author checklist

@github-actions
Copy link
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.

@metamaskbot metamaskbot added team-extension-platform Extension Platform team INVALID-PR-TEMPLATE PR's body doesn't match template labels Feb 24, 2026
@MajorLift MajorLift changed the title Handle null URLs in E2E mock server and ignore ERR_BLOCKED_BY_CLIENT console errors ci: Handle null URLs in E2E mock server and ignore ERR_BLOCKED_BY_CLIENT console errors Feb 24, 2026
@MajorLift MajorLift changed the title ci: Handle null URLs in E2E mock server and ignore ERR_BLOCKED_BY_CLIENT console errors Fix null extension ID and ERR_BLOCKED_BY_CLIENT errors in E2E tests Feb 24, 2026
@MajorLift MajorLift changed the title Fix null extension ID and ERR_BLOCKED_BY_CLIENT errors in E2E tests ci: Fix null extension ID and ERR_BLOCKED_BY_CLIENT errors in E2E tests Feb 24, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [88c32ff]
⚡ Performance Benchmarks (1374 ± 111 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account27210266288
total27210266288
Confirm Txconfirm_tx6037860446046
total6037860446046
Bridge User Actionsbridge_load_page24130272274
bridge_load_asset_picker17563245258
bridge_search_token71324730752
total11306012041204
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup13741157183711114191574
load117198615709712081349
domContentLoaded116297315229412011326
domInteractive2817105182578
firstPaint1526745887204352
backgroundConnect20318525714206236
firstReactRender18124041923
initialActions106113
loadScripts97678613249410161140
setupStore1363851621
numNetworkReqs312291192285
Chrome Browserify Startup Power User HomeuiStartup18091362921179418062305
load1119990168914111061503
domContentLoaded1103984164813410941470
domInteractive3318128203382
firstPaint1606737072220282
backgroundConnect3312503042306290487
firstReactRender23164862632
initialActions105113
loadScripts90478814531328911271
setupStore1776381932
numNetworkReqs60341482565117
Chrome Webpack Startup Standard HomeuiStartup84269111881058851078
load711604102689750884
domContentLoaded705600102089746879
domInteractive271599192280
firstPaint1155761979134231
backgroundConnect27195572939
firstReactRender18114462132
initialActions105112
loadScripts703598101888745874
setupStore1263661321
numNetworkReqs3122100212589
Chrome Webpack Startup Power User HomeuiStartup1234884184414313301453
load74465711041047351047
domContentLoaded73465010961057241038
domInteractive3720162273684
firstPaint1486841674177294
backgroundConnect17513531942175275
firstReactRender24174042730
initialActions102011
loadScripts73164810871037221025
setupStore1355971521
numNetworkReqs953725950130185
Firefox Browserify Startup Standard HomeuiStartup16691416264324816732218
load14081190232020814331807
domContentLoaded14061185232020814271806
domInteractive793129649103140
firstPaint------
backgroundConnect61282053361140
firstReactRender13112221416
initialActions107122
loadScripts13791169228620114021678
setupStore228149281762
numNetworkReqs311994192580
Firefox Browserify Startup Power User HomeuiStartup27792113700457628853682
load16061300568348616472151
domContentLoaded16061295568248616462151
domInteractive12435611114110353
firstPaint------
backgroundConnect3151101124263366897
firstReactRender201480101924
initialActions113122
loadScripts15731275565648315942102
setupStore102773815098493
numNetworkReqs65261733584141
Firefox Webpack Startup Standard HomeuiStartup17551410377940117132132
load14681227352233514541640
domContentLoaded14671227352233514541639
domInteractive893227942120146
firstPaint------
backgroundConnect64283274662169
firstReactRender16122841725
initialActions103122
loadScripts14431203342832914301614
setupStore477186118741150
numNetworkReqs312090182783
Firefox Webpack Startup Power User HomeuiStartup26881971426540928743537
load15721229275829717542215
domContentLoaded15721229275729717542215
domInteractive148321380190126571
firstPaint------
backgroundConnect296115950231291860
firstReactRender2316119132333
initialActions213122
loadScripts15371215273429416682187
setupStore18210842235245695
numNetworkReqs63271793775137
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2181218219
srpButtonToSrpForm9329596
confirmSrpToPwForm2102122
pwFormToMetricsScreen1501515
metricsToWalletReadyScreen1601616
doneButtonToHomeScreen65570716732
openAccountMenuToAccountListLoaded749439176668055
total87048387788778
Onboarding New WalletcreateWalletToSocialScreen2181219220
srpButtonToPwForm1040105105
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3623639
agreeButtonToOnboardingSuccess1601617
doneButtonToAssetList89235313071319
total127535216871701
Asset DetailsassetClickToPriceChart51187273
total51187273
Solana Asset DetailsassetClickToPriceChart4624849
total4624849
Import Srp HomeloginToHomeScreen19437919592064
openAccountMenuAfterLogin4234147
homeAfterImportWithNewWallet243611924992595
total442111744284596
Send TransactionsopenSendPageFromHome2793939
selectTokenToSendFormLoaded2883142
reviewTransactionToConfirmationPage86315858889
total92020922951
SwapopenSwapPageFromHome11311120127
fetchAndDisplaySwapQuotes559979662496261
total571279663546376
🌐 Dapp Page Load Benchmarks

Current Commit: 88c32ff | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.00s (±41ms) 🟡 | historical mean value: 1.05s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 694ms (±36ms) 🟢 | historical mean value: 731ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 77ms (±10ms) 🟢 | historical mean value: 82ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.00s 41ms 976ms 1.30s 1.03s 1.30s
domContentLoaded 694ms 36ms 670ms 958ms 718ms 958ms
firstPaint 77ms 10ms 60ms 156ms 88ms 156ms
firstContentfulPaint 77ms 10ms 60ms 156ms 88ms 156ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 5 Bytes (0%)
  • common: 20 Bytes (0%)

- Add retry logic (5x, 1s delay) to `getExtensionIdByName` shadow DOM query
  to handle race condition when `chrome://extensions` hasn't fully loaded
- Add null guard in `mock-e2e.js` `beforeRequest` handler to return 200 for
  requests with null/undefined host or URL
- Add `net::ERR_BLOCKED_BY_CLIENT` and `null is blocked` to default
  `ignoredConsoleErrors` in `driver.js`
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

✨ Files requiring CODEOWNER review ✨

🧪 @MetaMask/qa (1 files, +7 -0)
  • 📁 test/
    • 📁 e2e/
      • 📄 mock-e2e.js +7 -0

@sonarqubecloud
Copy link

@MajorLift MajorLift changed the title ci: Fix null extension ID and ERR_BLOCKED_BY_CLIENT errors in E2E tests ci: Fix flaky E2E failures from ERR_BLOCKED_BY_CLIENT extension ID race condition Feb 24, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [26c869c]
⚡ Performance Benchmarks (1359 ± 97 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2752276276
total2752276276
Confirm Txconfirm_tx60483160406100
total60483160406100
Bridge User Actionsbridge_load_page21427230260
bridge_load_asset_picker17938199237
bridge_search_token7034702709
total10871110861104
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup1359115716589714001560
load114696314579211791328
domContentLoaded113995914499011731312
domInteractive2616126202378
firstPaint170661473184204341
backgroundConnect19918525312201225
firstReactRender19124752026
initialActions107114
loadScripts9557741262909851133
setupStore1262941319
numNetworkReqs312289202285
Chrome Browserify Startup Power User HomeuiStartup19811581993891819542448
load11691027174114012011485
domContentLoaded11521012163013111881466
domInteractive3418197243471
firstPaint1667252786219318
backgroundConnect4202587472754313549
firstReactRender25165072741
initialActions109114
loadScripts94481513751269671253
setupStore1664071930
numNetworkReqs66351512475125
Chrome Webpack Startup Standard HomeuiStartup8536981157898791019
load72762193181773887
domContentLoaded72161892580767878
domInteractive281799192575
firstPaint12762807111129276
backgroundConnect30197393442
firstReactRender19133962134
initialActions106112
loadScripts71861691679765876
setupStore1363861424
numNetworkReqs312292202589
Chrome Webpack Startup Power User HomeuiStartup1242878231022413161744
load7366291174108736988
domContentLoaded7256221126105723982
domInteractive36191593132120
firstPaint1446745683165317
backgroundConnect18113556061172294
firstReactRender23163642531
initialActions104111
loadScripts7226191116103721972
setupStore1355861519
numNetworkReqs1083524851143215
Firefox Browserify Startup Standard HomeuiStartup16571394286021816502029
load13941202250517914231574
domContentLoaded13931202250417914221574
domInteractive91361088108114149
firstPaint------
backgroundConnect5930226276182
firstReactRender13112421414
initialActions103122
loadScripts13681174247217613981550
setupStore2572193916142
numNetworkReqs321997212692
Firefox Browserify Startup Power User HomeuiStartup26621945429041828723434
load15611229313229316492012
domContentLoaded15601229313229316492011
domInteractive149371770201121416
firstPaint------
backgroundConnect2971171052228317843
firstReactRender18147891721
initialActions103122
loadScripts15211209310928615921968
setupStore1568751206174629
numNetworkReqs67281643883145
Firefox Webpack Startup Standard HomeuiStartup17641459323123818002066
load14951231294621215181702
domContentLoaded14951231294621215181702
domInteractive114311395138131182
firstPaint------
backgroundConnect64282844069147
firstReactRender16123541625
initialActions102122
loadScripts14681216290620814941659
setupStore257169273860
numNetworkReqs311991172778
Firefox Webpack Startup Power User HomeuiStartup27602032522451328733757
load16231332355736117102181
domContentLoaded16231332355636117102181
domInteractive15437964184122638
firstPaint------
backgroundConnect2971241128231305889
firstReactRender21156872329
initialActions217123
loadScripts15801315351434116551997
setupStore14912650176181549
numNetworkReqs69272524081133
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2182220221
srpButtonToSrpForm9219292
confirmSrpToPwForm2212324
pwFormToMetricsScreen1501616
metricsToWalletReadyScreen1601616
doneButtonToHomeScreen92230712001323
openAccountMenuToAccountListLoaded737734677517828
total87753087988798
Onboarding New WalletcreateWalletToSocialScreen2181218220
srpButtonToPwForm1062108108
createPwToRecoveryScreen8089
skipBackupToMetricsScreen3723839
agreeButtonToOnboardingSuccess1601616
doneButtonToAssetList81239112851295
total119839016711679
Asset DetailsassetClickToPriceChart4014141
total4014141
Solana Asset DetailsassetClickToPriceChart4514646
total4514646
Import Srp HomeloginToHomeScreen19385319432017
openAccountMenuAfterLogin4264850
homeAfterImportWithNewWallet245811225422628
total44169744614547
Send TransactionsopenSendPageFromHome28103842
selectTokenToSendFormLoaded2993941
reviewTransactionToConfirmationPage8523852856
total9133918918
SwapopenSwapPageFromHome13111141143
fetchAndDisplaySwapQuotes46355546634728
total47506947874845
🌐 Dapp Page Load Benchmarks

Current Commit: 26c869c | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±49ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 723ms (±42ms) 🟢 | historical mean value: 729ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 77ms (±11ms) 🟢 | historical mean value: 82ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 49ms 1.01s 1.33s 1.07s 1.33s
domContentLoaded 723ms 42ms 700ms 1.00s 747ms 1.00s
firstPaint 77ms 11ms 60ms 168ms 88ms 168ms
firstContentfulPaint 77ms 11ms 60ms 168ms 88ms 168ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 42 Bytes (0%)
  • common: 20 Bytes (0%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template size-S team-extension-platform Extension Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants