You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Safari 26.3 on macOS (not reproduced on Chromium — see below)
Expected behavior
When a map is removed via map.remove() or its style is swapped via map.setStyle(), any in-flight worker tile-load messages should either be cancelled before their main-thread callback runs, or the callback should be guarded against this.style being undefined. No TypeError should reach the window error handler.
Actual behavior
A worker message event handler invokes a tile-load callback after the map's style has been torn down. Two distinct stacks are observed in production, both originating from Actor.receive →
processTask on the main thread, both ultimately dereferencing a now-undefined style:
loadVectorData path:
TypeError: undefined is not an object (evaluating 'l.style.imageManager')
at loadVectorData
at processTask
at receive
Throws inside the hasSymbolBuckets / hasRTLText branch when touching this.style.imageManager.
refreshFeatureState path:
TypeError: undefined is not an object (evaluating 'f.style.listImages')
at refreshFeatureState
at initializeTileState
at _tileLoaded
at processTask
at receive
No reliable minimal repro yet — the race is timing-dependent and we've only seen it in production. If useful, I can share anonymized Sentry events and session replays separately.
Steps to trigger the unexpected behavior
Not deterministic, but in production the error fires when one of the following happens while vector tiles are in flight:
The component owning the map is unmounted (calls map.remove()), or
map.setStyle() is invoked to switch between a light/dark/satellite style.
In both cases, a worker message already in the Safari event queue is dispatched after map.style has been nulled. Chromium tends to drain queued worker messages before teardown completes,
which is likely why we don't see this stack from non-Safari users.
Stacktrace js:
TypeError: undefined is not an object (evaluating 'f.style.listImages')
at refreshFeatureState (/assets/vendor-CnBHFJ2o.js:538:542567)
at initializeTileState (/assets/vendor-CnBHFJ2o.js:539:75049)
at _tileLoaded (/assets/vendor-CnBHFJ2o.js:539:80134)
at processTask (/assets/vendor-CnBHFJ2o.js:538:530331)
at receive (/assets/vendor-CnBHFJ2o.js:538:530172)
at r (/assets/vendor-CnBHFJ2o.js:479:9531)
----
This is most likely a bug, please report this via https://github.com/mapbox/mapbox-gl-js/issues/new?assignees=&labels=&template=Bug_report.md
and paste the contents of this message in the report.
Thank you!
Filter Expression:
${JSON.stringify(b,null,2)}
{snip} .state="expired"):this.expiredRequestCount=0}}getExpiryTimeout(){if(this.expirationTime)return this.expiredRequestCount?1e3*(1<<Math.min(thi {snip}{snip} t.terrain)}}_c.getSourceType=function(S){return Bc[S]},_c.setSourceType=function(S,d){Bc[S]=d},_c.registerForPluginStateChange=o.dg;var kh=`#define EPSILON 0.0000001#define PI 3.141592653589793#ifdef RENDER_CUTOFF{snip} utoffEnd=cutoff_params.w;float linearDepth=(depth-near)/(far-near);return clamp((linearDepth-cutoffStart)/(cutoffEnd-cutoffStart),0.0,1.0);}
mapbox-gl-js version
v3.21.0
Browser and version
Safari 26.3 on macOS (not reproduced on Chromium — see below)
Expected behavior
When a map is removed via map.remove() or its style is swapped via map.setStyle(), any in-flight worker tile-load messages should either be cancelled before their main-thread callback runs, or the callback should be guarded against this.style being undefined. No TypeError should reach the window error handler.
Actual behavior
A worker message event handler invokes a tile-load callback after the map's style has been torn down. Two distinct stacks are observed in production, both originating from Actor.receive →
processTask on the main thread, both ultimately dereferencing a now-undefined style:
TypeError: undefined is not an object (evaluating 'l.style.imageManager')
at loadVectorData
at processTask
at receive
TypeError: undefined is not an object (evaluating 'f.style.listImages')
at refreshFeatureState
at initializeTileState
at _tileLoaded
at processTask
at receive
entry points or a regression has reintroduced the race on another path.
Link to the demonstration
No reliable minimal repro yet — the race is timing-dependent and we've only seen it in production. If useful, I can share anonymized Sentry events and session replays separately.
Steps to trigger the unexpected behavior
Not deterministic, but in production the error fires when one of the following happens while vector tiles are in flight:
In both cases, a worker message already in the Safari event queue is dispatched after map.style has been nulled. Chromium tends to drain queued worker messages before teardown completes,
which is likely why we don't see this stack from non-Safari users.
Relevant log output
/assets/vendor-CnBHFJ2o.js:538:536512 (loadVectorData)
/assets/vendor-CnBHFJ2o.js:538:530331 (processTask)
/assets/vendor-CnBHFJ2o.js:538:530172 (receive)
/assets/vendor-CnBHFJ2o.js:538:542567 (refreshFeatureState)
/assets/vendor-CnBHFJ2o.js:539:75049 (initializeTileState)
/assets/vendor-CnBHFJ2o.js:539:80134 (_tileLoaded)
/assets/vendor-CnBHFJ2o.js:538:530331 (processTask)
/assets/vendor-CnBHFJ2o.js:538:530172 (receive)
User-agent: Safari 26.3, macOS >=10.15.7
Related
Relevant log output