#17281·openlayers

WebGL renderer: conditional buffer deletion avoids crash but leaves stale references after helper removal

Author: ju-pietCreated Jan 8, 2026Updated Jul 16, 2026
Labelsbug

Description

This issue is related to (and builds upon) the following OpenLayers bug report:
https://github.com/openlayers/openlayers/issues/16649

We are encountering the same WebGL lifecycle problem where the WebGL helper is removed before all renderer-owned GPU resources are properly disposed.

Context

When a WebGL layer is removed or disposed, removeHelper() is called and the WebGL context / helper may already be undefined while internal buffers are still referenced by the renderer.

This results in crashes when attempting to delete buffers via the helper.

Current workaround

To avoid the crash, we added a defensive check when deleting buffers:

typescript
for (const buffer of typeBuffers) {   
	if (buffer) {     
	// Helper might already be undefined.     
	// See https://github.com/openlayers/openlayers/issues/16649     
	this.helper?.deleteBuffer(buffer);   
	} 
}

This prevents runtime errors when the helper is missing.

Remaining problem: stale references

While this avoids the crash, the underlying reference issue still exists:

  • When helper is already undefined, the WebGL buffers cannot be deleted on the GPU side.
  • The renderer still keeps references to these WebGLBuffer objects in internal structures (typeBuffers, caches, etc.).
  • These stale references can later:
    • cause double-deletion attempts,
    • be reused during rebuilds,
    • or lead to memory leaks and undefined WebGL behavior.

In other words, the fix avoids the exception but does not fully clean up renderer state.

Why this is problematic

From an application point of view, it is impossible to reliably dispose a WebGL layer without risking:

  • incomplete cleanup (memory leaks),
  • lingering CPU-side references,
  • or inconsistent renderer state after helper removal.

This also makes it difficult to implement safe lifecycle management (e.g. dynamic add/remove layers, style rebuilds, React unmounts).