Skip to content

fix: nft image startsWith error#40413

Merged
Prithpal-Sooriya merged 1 commit intomainfrom
cursor/nft-image-startswith-error-e434
Feb 26, 2026
Merged

fix: nft image startsWith error#40413
Prithpal-Sooriya merged 1 commit intomainfrom
cursor/nft-image-startswith-error-e434

Conversation

@Prithpal-Sooriya
Copy link
Contributor

@Prithpal-Sooriya Prithpal-Sooriya commented Feb 25, 2026

Description

Fixes TypeError: Pe.startsWith is not a function when loading NFT images by ensuring nftSrcUrl is a string.

The error occurred because nftSrcUrl could be a non-string value (e.g., an object or number) if the NFT metadata from the token URI contained a non-string image field. The optional chaining (?.) only guards against null/undefined, not against calling .startsWith() on a defined non-string value. This PR adds explicit type checks to prevent this.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: fix: nft image startsWith error

Related issues

Fixes: #40412 https://consensyssoftware.atlassian.net/browse/ASSETS-2793

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

After

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.

Open in Web Open in Cursor 


Note

Low Risk
Small defensive type-guard changes plus a unit test; behavior only changes for malformed/unsupported tokenURI metadata.

Overview
Prevents a runtime crash in NFT details rendering by only calling startsWith('ipfs:') when the computed nftSrcUrl is actually a string.

Hardens useFetchNftDetailsFromTokenURI to only populate image/name when the tokenURI JSON fields are strings, and adds a test case covering non-string metadata responses.

Written by Cursor Bugbot for commit e7e5afd. This will update automatically on new commits. Configure here.

Fixes #40412

The error 'Pe.startsWith is not a function' occurred because nftSrcUrl
could be a non-string value (e.g., object, array, number) when the NFT
metadata returned from token URI contained a non-string image field.

Changes:
- In useFetchNftDetailsFromTokenURI.ts: validate that data.image and
  data.name are strings before setting state
- In nft-details.tsx: add type guard to ensure nftSrcUrl is a string
  before calling .startsWith()
- Added test case to verify non-string image/name values are ignored

Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
@cursor
Copy link

cursor bot commented Feb 25, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 25, 2026

✨ Files requiring CODEOWNER review ✨

💎 @MetaMask/metamask-assets (1 files, +2 -1)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 assets/
          • 📁 nfts/
            • 📁 nft-details/
              • 📄 nft-details.tsx +2 -1

@sonarqubecloud
Copy link

@Prithpal-Sooriya Prithpal-Sooriya changed the title Nft image startsWith error fix: nft image startsWith error Feb 25, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 25, 2026

Builds ready [e7e5afd]
⚡ Performance Benchmarks (1417 ± 111 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account27211277291
total27211277291
Confirm Txconfirm_tx60421860596067
total60421860596067
Bridge User Actionsbridge_load_page24047294298
bridge_load_asset_picker21828223260
bridge_search_token72017734738
total11725512101233
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup14171186178811114661612
load118899014709612271369
domContentLoaded118098714649412161363
domInteractive2917101192585
firstPaint180691205161218366
backgroundConnect21319536219214239
firstReactRender2113174162131
initialActions107114
loadScripts98479312469210221168
setupStore1373151624
numNetworkReqs312290192283
Chrome Browserify Startup Power User HomeuiStartup2970153110500207836939325
load12311051179914812631575
domContentLoaded12111037174213812461504
domInteractive3519169213470
firstPaint218731651215267373
backgroundConnect10652648125145011394441
firstReactRender25155172738
initialActions108112
loadScripts996827153513510231278
setupStore1564361726
numNetworkReqs79411502492127
Chrome Webpack Startup Standard HomeuiStartup8867171186999401093
load762635101092822921
domContentLoaded757631100391816906
domInteractive3017140232592
firstPaint1266840766160245
backgroundConnect29206383243
firstReactRender1912119122131
initialActions104112
loadScripts75462999390814896
setupStore1264051218
numNetworkReqs312298202585
Chrome Webpack Startup Power User HomeuiStartup1357950315537014002273
load77567413931277701072
domContentLoaded76366513801287601061
domInteractive40211682936103
firstPaint1467340874167298
backgroundConnect2241361366211180658
firstReactRender22174242428
initialActions103111
loadScripts76066313681257581056
setupStore1354351619
numNetworkReqs1014421234116167
Firefox Browserify Startup Standard HomeuiStartup16031350265620516311961
load13461138218814914001612
domContentLoaded13451138218714913991610
domInteractive75322334591149
firstPaint------
backgroundConnect60283424157132
firstReactRender13111811416
initialActions103012
loadScripts13191117215814213761535
setupStore156113121430
numNetworkReqs311999212591
Firefox Browserify Startup Power User HomeuiStartup28762116873168629913367
load16221320726859016261926
domContentLoaded16211320726759016241925
domInteractive15649516115178448
firstPaint------
backgroundConnect45710814213377001088
firstReactRender211570122063
initialActions2043422
loadScripts15831301722658815841875
setupStore16711785193219616
numNetworkReqs82322183991177
Firefox Webpack Startup Standard HomeuiStartup17181444333424617531992
load14531228298722414791616
domContentLoaded14521227298722514781615
domInteractive953029848132163
firstPaint------
backgroundConnect63271873369130
firstReactRender16135451625
initialActions103122
loadScripts14261200295622114501583
setupStore208155241650
numNetworkReqs311998182778
Firefox Webpack Startup Power User HomeuiStartup28722112843486429553490
load16721281714575816722126
domContentLoaded16721281714475816722126
domInteractive179391396203171564
firstPaint------
backgroundConnect42412515453075951021
firstReactRender231679102431
initialActions2028322
loadScripts16261260710375916292106
setupStore14011735168137522
numNetworkReqs85322414187168
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2201221221
srpButtonToSrpForm97298100
confirmSrpToPwForm2312325
pwFormToMetricsScreen1611717
metricsToWalletReadyScreen1711818
doneButtonToHomeScreen101529711871386
openAccountMenuToAccountListLoaded762133279288045
total901013491029177
Onboarding New WalletcreateWalletToSocialScreen2191220220
srpButtonToPwForm1080108108
createPwToRecoveryScreen8099
skipBackupToMetricsScreen3713839
agreeButtonToOnboardingSuccess1701717
doneButtonToAssetList680161808922
total107216011961312
Asset DetailsassetClickToPriceChart4134245
total4134245
Solana Asset DetailsassetClickToPriceChart4714849
total4714849
Import Srp HomeloginToHomeScreen18951119101910
openAccountMenuAfterLogin3733743
homeAfterImportWithNewWallet21473121542190
total41088841434227
Send TransactionsopenSendPageFromHome35114346
selectTokenToSendFormLoaded2212323
reviewTransactionToConfirmationPage8591448961093
total9161369581137
SwapopenSwapPageFromHome14027145178
fetchAndDisplaySwapQuotes631410764276460
total64338364976559
🌐 Dapp Page Load Benchmarks

Current Commit: e7e5afd | Date: 2/25/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±53ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 740ms (±48ms) 🟢 | historical mean value: 731ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 82ms (±15ms) 🟢 | historical mean value: 79ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 53ms 1.02s 1.44s 1.10s 1.44s
domContentLoaded 740ms 48ms 716ms 1.09s 765ms 1.09s
firstPaint 82ms 15ms 68ms 220ms 92ms 220ms
firstContentfulPaint 82ms 15ms 68ms 220ms 92ms 220ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 61 Bytes (0%)
  • common: 20 Bytes (0%)

@Prithpal-Sooriya Prithpal-Sooriya marked this pull request as ready for review February 25, 2026 18:22
@Prithpal-Sooriya Prithpal-Sooriya requested a review from a team as a code owner February 25, 2026 18:22
}
if (typeof data.name === 'string') {
setName(data.name);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not able to repro the bug locally for the reported NFT ; but trying to use a malformed data worked (screenshot)
Most NFTs return { "image": "https://..." } (a string). But some return malformed metadata like { "image": { "url": "https://..." } } or { "image": ["img1", "img2"] } ; an object or array instead of a string; the UI wont know what to do with this so better not call setImage;

The component uses the value as a fallback when imageOriginal and image are both missing:
const nftSrcUrl = imageOriginal ?? image ?? imageFromTokenURI;
So in case we fallback to imageFromTokenURI it will be empty

Image

@Prithpal-Sooriya Prithpal-Sooriya added this pull request to the merge queue Feb 26, 2026
Merged via the queue into main with commit 4c2c0cc Feb 26, 2026
200 of 205 checks passed
@Prithpal-Sooriya Prithpal-Sooriya deleted the cursor/nft-image-startswith-error-e434 branch February 26, 2026 11:00
@github-actions github-actions bot locked and limited conversation to collaborators Feb 26, 2026
@metamaskbot metamaskbot added the release-13.21.0 Issue or pull request that will be included in release 13.21.0 label Feb 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.21.0 Issue or pull request that will be included in release 13.21.0 size-S team-assets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Sentry] TypeError: Pe.startsWith is not a function

6 participants