A time-enabled vectortile layer that is switched on gets rebuilt whenever the
timeline moves. The rebuild draws a second copy of the layer without removing
the first, and switching the layer off afterwards removes only one of them.
The other stays on the map for the rest of the session, with the layer
recorded as off and its checkbox cleared. Nothing in the interface can get rid
of it; only reloading the page will.
Reproducing it
On a Leaflet mission with a time-enabled vectortile layer:
- Switch the layer on.
- Move the timeline.
- Switch the layer off.
The layer is still drawn. Repeating the cycle strands another copy each time.
Counted as the number of layers the map holds, this goes 7 → 8 on the rebuild
and back to 7 when the layer is switched off — one more than it started with,
and the copy left behind is the one built before the rebuild.
Why it only shows up in some places
Only some layer types are rebuilt this way. Raster tile layers recompute their
address in place and are never reconstructed, so they never accumulate. Vector
layers are reconstructed, but their builder is told that it is replacing an
existing layer and clears the old one; the vectortile builder is never told and
never does.
It is also specific to the Leaflet renderer. Under deck.gl a rebuilt layer
replaces the entry held under the same identifier, so the old one is dropped
rather than stranded.
What we want
A layer that is rebuilt while it is on is drawn once, not twice, and switching
it off afterwards leaves nothing behind.
Acceptance
- A time-enabled vectortile layer that is on, after the timeline moves, is
drawn exactly once.
- Switching it off then removes it completely — the map holds the same number
of layers as before it was switched on.
- Repeating the on / move timeline / off cycle several times leaves nothing
accumulated.
- The other layer types that are rebuilt the same way behave the same, or the
gap is documented if it cannot be closed for one of them.
- Behaviour under deck.gl is unchanged.
Out of scope
- Resolving a vectortile layer's time when it is built, which is its own
problem and would only change how often the rebuild is triggered, not what
the rebuild leaves behind.
Implementation sketch — written as of 25ae2c5c on 2026-09-03; a rough guide, re-verify against latest
Where it lands: the vectortile builder in the map module, and the
layer-construction dispatcher that calls it.
Current shape. The dispatcher takes a flag meaning "this is a rebuild, not
a first build" and forwards it to the vector builder alone. Every other builder
is called without it. The vectortile builder therefore constructs a fresh
native layer and assigns it over the registry entry, and nothing removes the
native layer the previous build had already put on the map. The refresh path
then shows the newly built one, so both end up drawn.
Rough plan. Give the vectortile builder the same awareness the vector
builder has: when it is replacing an existing layer, take the previous native
layer off the map before overwriting the registry entry. Worth checking the
other builders that are called without the flag at the same time — the data,
image and video builders are in the same position, though whether they are ever
rebuilt in practice needs confirming.
⚠️ Gotcha: deck.gl does not show this symptom, because its registry is keyed
by identifier and re-registering replaces the entry. A fix verified only under
deck.gl will pass without proving anything — this has to be checked on Leaflet.
Testing. The observable is the number of layers the map holds before and
after a rebuild; asserting on it is more reliable than looking at the screen,
since the two copies are drawn on top of each other and look like one.
A time-enabled vectortile layer that is switched on gets rebuilt whenever the
timeline moves. The rebuild draws a second copy of the layer without removing
the first, and switching the layer off afterwards removes only one of them.
The other stays on the map for the rest of the session, with the layer
recorded as off and its checkbox cleared. Nothing in the interface can get rid
of it; only reloading the page will.
Reproducing it
On a Leaflet mission with a time-enabled vectortile layer:
The layer is still drawn. Repeating the cycle strands another copy each time.
Counted as the number of layers the map holds, this goes 7 → 8 on the rebuild
and back to 7 when the layer is switched off — one more than it started with,
and the copy left behind is the one built before the rebuild.
Why it only shows up in some places
Only some layer types are rebuilt this way. Raster tile layers recompute their
address in place and are never reconstructed, so they never accumulate. Vector
layers are reconstructed, but their builder is told that it is replacing an
existing layer and clears the old one; the vectortile builder is never told and
never does.
It is also specific to the Leaflet renderer. Under deck.gl a rebuilt layer
replaces the entry held under the same identifier, so the old one is dropped
rather than stranded.
What we want
A layer that is rebuilt while it is on is drawn once, not twice, and switching
it off afterwards leaves nothing behind.
Acceptance
drawn exactly once.
of layers as before it was switched on.
accumulated.
gap is documented if it cannot be closed for one of them.
Out of scope
problem and would only change how often the rebuild is triggered, not what
the rebuild leaves behind.
Implementation sketch — written as of
25ae2c5con 2026-09-03; a rough guide, re-verify against latestWhere it lands: the vectortile builder in the map module, and the
layer-construction dispatcher that calls it.
Current shape. The dispatcher takes a flag meaning "this is a rebuild, not
a first build" and forwards it to the vector builder alone. Every other builder
is called without it. The vectortile builder therefore constructs a fresh
native layer and assigns it over the registry entry, and nothing removes the
native layer the previous build had already put on the map. The refresh path
then shows the newly built one, so both end up drawn.
Rough plan. Give the vectortile builder the same awareness the vector
builder has: when it is replacing an existing layer, take the previous native
layer off the map before overwriting the registry entry. Worth checking the
other builders that are called without the flag at the same time — the data,
image and video builders are in the same position, though whether they are ever
rebuilt in practice needs confirming.
by identifier and re-registering replaces the entry. A fix verified only under
deck.gl will pass without proving anything — this has to be checked on Leaflet.
Testing. The observable is the number of layers the map holds before and
after a rebuild; asserting on it is more reliable than looking at the screen,
since the two copies are drawn on top of each other and look like one.