TypeError: Cannot read properties of undefined (reading 'get') when a map is removed while a color-theme LUT is decoding
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- frontend
Research direction
Start in src/style/style.ts at Style._loadColorTheme, where lutImage.onload only checks lutLoadingCorrelationID before calling getImage; cross-reference src/render/image_manager.ts (ImageManager.getImage, removeScope) to see why a removed scope makes it throw. Reproduce by delaying onload for data:image/png images and calling map.remove() before the LUT decodes. Done means no uncaught exception on that path and a regression test covering the race, verifying that simply calling resolve() still fails later in _reloadImports/addImages.
Written by the indexing model from the issue text.
Description
mapbox-gl-js version: 3.31.0. The same code is in 3.32.0 and 3.33.0-rc.1, and it also reproduces on 3.15.0.
Browser/OS: any. We first saw it in production on Edge on Windows, and reproduced it in Chromium.
Steps to trigger
- Create a map whose style has a non-empty
color-theme. For example, a style that imports
mapbox://styles/mapbox/standardwithconfig.theme: "faded". - Call
map.remove(), or replace the map's style, after the style JSON is parsed but before the
LUTImagefiresonload.
You can make it deterministic by delaying onload for data:image/png images by a few seconds,
then calling map.remove() as soon as the LUT image decodes.
Expected
No error. The removed style should drop the pending LUT load.
Actual
An uncaught exception from the Image.onload handler:
TypeError: Cannot read properties of undefined (reading 'get')
at ImageManager.getImage (src/render/image_manager.ts:189)
at Style.getImage (src/style/style.ts:2407)
at lutImage.onload (src/style/style.ts:1599)
map.remove() → Style.destroy() → fragment.style._remove() → imageManager.removeScope(scope)
deletes the scope. The lutImage.onload in Style._loadColorTheme only checks
lutLoadingCorrelationID, so it then calls getImage on a scope that no longer exists.
Suggested fix
Bail out of onload when the style has been removed, without settling the promise:
lutImage.onload = () => {
if (!this.imageManager.images.has(this.scope)) return; // style was removed
if (this._styleColorTheme.lutLoadingCorrelationID !== correlationID) { ... }
Calling resolve() here is not enough. It runs proceedWithStyleLoad() on the removed style, which
then throws in _reloadImports (_initialBroadcastDone) and in addImages.
- Dominant language
- TypeScript
- Stars
- 12.5k
- Forks
- 2.4k
- PR merge metrics
- No merged PRs in 30d
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from mapbox/mapbox-gl-js
-
auto-triaged bug :lady_beetle:
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
mapbox/mapbox-gl-js#13723 · 2 comments ·
-
auto-triaged bug :lady_beetle:
Difficulty 1/5 Under an hour Newbie friendliness 86/100
mapbox/mapbox-gl-js#13717 ·
-
>= v3.21 Symbol layer without feature-state expression crash the mapPossibly taken @liueric-dev claimed this 60 days ago. Openauto-triaged bug :lady_beetle:
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
mapbox/mapbox-gl-js#13714 · 1 reaction ·
-
auto-triaged feature :green_apple:
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
mapbox/mapbox-gl-js#13676 · 2 comments ·
-
docs :scroll:
Difficulty 1/5 Under an hour Newbie friendliness 68/100
mapbox/mapbox-gl-js#13523 ·
All issues in mapbox/mapbox-gl-js
Similar issues
-
ready
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
wheresrhys/totf#1214 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
CodeChefVIT/ffcs#281 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
endora-commerce/endora-commerce#451 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
vetro-protocol/vetro-monorepo#1007 ·
Maintainers usually reply within 1 day