Description
When a WMS layer's loadingError state transitions from no-error to "Error", WMSLayer.js (openlayers plugin, update function) unconditionally calls wmsSource.refresh(), which drops the tile cache and re-requests every currently visible tile. This is meant to help recover from a one-off configuration mistake (per the existing code comment, e.g. "incorrect time dimension date filter") that gets fixed externally, where one automatic reload picks up the corrected data. It has no attempt counter and no cooldown.
The trigger itself is generic (it fires whenever loadingError flips from anything else to "Error", for any tile load failure — no security/authentication configuration required), but note the loop specifically requires the error state to oscillate (fail, then recover, then fail again), not just fail once permanently — the check only reacts to a false → true transition, so a layer that fails deterministically and stays failed only triggers one refresh(), not a loop. The loop shows up when the underlying failure is intermittent: something that fails sometimes and not other times for the same layer/tile (e.g. a security/auth check with an occasional race condition, or a backend with a short timeout and limited concurrency that can't always keep up with a full-viewport burst of concurrent tile requests). In that situation, the refresh()'s own fresh burst of tile requests recreates the same conditions that caused the original failure, so it has a real chance of failing again — flipping loadingError to "Error" again, triggering another refresh(), and so on. Visually the layer flashes/reloads without ever settling, and the browser keeps sending WMS requests indefinitely.
How to reproduce
This requires a WMS backend that intermittently fails a fraction of concurrent tile requests (not a permanently broken layer, which only triggers the refresh once and then stays in a stable error state). We reproduced it against a real backend under the following conditions:
- A secured WMS layer (tiles carry an auth token as a URL parameter, validated server-side).
- The security check occasionally fails validation for a token that is valid moments later (session/timing-dependent, not a fixed misconfiguration).
- Loading the map at a zoom level that requests 10+ tiles concurrently, so each reload attempt has multiple chances to hit the intermittent failure.
Expected Result
A tile load failure should trigger at most a small, bounded number of automatic layer refreshes. If the failure keeps recurring, MapStore should stop auto-refreshing and leave the tile(s) in a visibly-errored state rather than retrying forever.
Current Result
Every time loadingError flips to "Error" again, wmsSource.refresh() fires again, unconditionally, with no limit. Reproduced against a real intermittently-failing backend: the same ~16 tiles for one layer were re-requested upwards of 170 times within 20 seconds, with the refresh() call itself observed firing 56 times consecutively in a single session (confirmed via added instrumentation logging, not inferred from network traffic alone).
Browser info
| Browser Affected |
Version |
| Chrome |
150 (also expected on any browser, mechanism is not browser-specific) |
Other useful information
Relevant code: web/client/components/map/openlayers/plugins/WMSLayer.js, update function:
// refresh/update wms layer if there is error in loading tiles like: incorrect time dimension date filter, ..etc
if (oldOptions.loadingError !== "Error" && newOptions.loadingError === "Error") {
wmsSource?.tileCache?.pruneExceptNewestZ?.();
wmsSource?.refresh();
}
Suggested fix: track consecutive auto-refresh attempts per layer within a cooldown window (e.g. max 3 attempts per 30s, counter reset only after a real quiet period — not on every transient recovery, since the loop itself involves the error state oscillating rapidly, which would otherwise reset the counter before it ever caps). PR to follow.
Description
When a WMS layer's
loadingErrorstate transitions from no-error to"Error",WMSLayer.js(openlayers plugin,updatefunction) unconditionally callswmsSource.refresh(), which drops the tile cache and re-requests every currently visible tile. This is meant to help recover from a one-off configuration mistake (per the existing code comment, e.g. "incorrect time dimension date filter") that gets fixed externally, where one automatic reload picks up the corrected data. It has no attempt counter and no cooldown.The trigger itself is generic (it fires whenever
loadingErrorflips from anything else to"Error", for any tile load failure — no security/authentication configuration required), but note the loop specifically requires the error state to oscillate (fail, then recover, then fail again), not just fail once permanently — the check only reacts to afalse → truetransition, so a layer that fails deterministically and stays failed only triggers onerefresh(), not a loop. The loop shows up when the underlying failure is intermittent: something that fails sometimes and not other times for the same layer/tile (e.g. a security/auth check with an occasional race condition, or a backend with a short timeout and limited concurrency that can't always keep up with a full-viewport burst of concurrent tile requests). In that situation, therefresh()'s own fresh burst of tile requests recreates the same conditions that caused the original failure, so it has a real chance of failing again — flippingloadingErrorto"Error"again, triggering anotherrefresh(), and so on. Visually the layer flashes/reloads without ever settling, and the browser keeps sending WMS requests indefinitely.How to reproduce
This requires a WMS backend that intermittently fails a fraction of concurrent tile requests (not a permanently broken layer, which only triggers the refresh once and then stays in a stable error state). We reproduced it against a real backend under the following conditions:
Expected Result
A tile load failure should trigger at most a small, bounded number of automatic layer refreshes. If the failure keeps recurring, MapStore should stop auto-refreshing and leave the tile(s) in a visibly-errored state rather than retrying forever.
Current Result
Every time
loadingErrorflips to"Error"again,wmsSource.refresh()fires again, unconditionally, with no limit. Reproduced against a real intermittently-failing backend: the same ~16 tiles for one layer were re-requested upwards of 170 times within 20 seconds, with therefresh()call itself observed firing 56 times consecutively in a single session (confirmed via added instrumentation logging, not inferred from network traffic alone).Browser info
Other useful information
Relevant code:
web/client/components/map/openlayers/plugins/WMSLayer.js,updatefunction:Suggested fix: track consecutive auto-refresh attempts per layer within a cooldown window (e.g. max 3 attempts per 30s, counter reset only after a real quiet period — not on every transient recovery, since the loop itself involves the error state oscillating rapidly, which would otherwise reset the counter before it ever caps). PR to follow.