Skip to content

Commit fac6fa1

Browse files
authored
prevent crash from missing account (MetaMask#8604)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> Stop crash that occurs when there is a missing entry in the `internalAccount` object. https://metamask.sentry.io/issues/7394639158/?project=273505&query=is%3Aunresolved%20Cannot%20read%20properties%20of%20undefined&referrer=issue-stream https://metamask.sentry.io/issues/6977774458/?project=273505&query=is%3Aunresolved%20Cannot%20read%20properties%20of%20undefined&referrer=issue-stream ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> ## Checklist - [X] I've updated the test suite for new or updated code as appropriate - [X] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [X] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [X] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small defensive change in a selector plus a unit test; behavior only changes for inconsistent state where an account ID is missing. > > **Overview** > Prevents `selectAssetsBySelectedAccountGroup` from crashing when an `accountTree` group references an account ID that is missing from `internalAccounts` by skipping those entries during account mapping. > > Adds a regression test covering the missing-account scenario and documents the fix in the assets-controllers changelog. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 78aa9aa. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent c947237 commit fac6fa1

3 files changed

Lines changed: 20 additions & 0 deletions

File tree

packages/assets-controllers/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- Malicious tokens that slip through are caught by the periodic rescan (runs daily by default)
2828
- Bump `@metamask/transaction-controller` from `^64.3.0` to `^64.4.0` ([#8585](https://github.com/MetaMask/core/pull/8585))
2929

30+
### Fixed
31+
32+
- Fix `selectAssetsBySelectedAccountGroup` crashing when an account referenced in the account tree is missing from internal accounts ([#8604](https://github.com/MetaMask/core/pull/8604))
33+
3034
## [104.3.0]
3135

3236
### Added

packages/assets-controllers/src/selectors/token-selectors.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,18 @@ describe('token-selectors', () => {
877877
expect(result).toStrictEqual(expectedMockResult);
878878
});
879879

880+
it('skips accounts referenced in accountTree but missing from internalAccounts', () => {
881+
const state = cloneDeep(mockedMergedState);
882+
883+
state.accountTree.wallets['entropy:01K1TJY9QPSCKNBSVGZNG510GJ'].groups[
884+
'entropy:01K1TJY9QPSCKNBSVGZNG510GJ/0'
885+
].accounts.push('non-existent-account-id');
886+
887+
const result = selectAssetsBySelectedAccountGroup(state);
888+
889+
expect(result).toStrictEqual(expectedMockResult);
890+
});
891+
880892
it('returns no tokens if there is no selected account group', () => {
881893
const result = selectAssetsBySelectedAccountGroup({
882894
...mockedMergedState,

packages/assets-controllers/src/selectors/token-selectors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ const selectAccountsToGroupIdMap = createAssetListSelector(
140140
for (const accountId of accounts) {
141141
const internalAccount = internalAccounts.accounts[accountId];
142142

143+
if (!internalAccount) {
144+
continue;
145+
}
146+
143147
accountsMap[
144148
// TODO: We would not need internalAccounts if evmTokens state had the accountId
145149
internalAccount.type.startsWith('eip155')

0 commit comments

Comments
 (0)