# WebGL.isWebGL2Available crashes renderer

**URL:** <https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335>\
**Category:** Questions\
**Tags:** webgl-renderer\
**Created:** [October 24, 2023, 1:26am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335 "2023-10-24T01:26:38Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![new](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/new/32/25580_2.png) [@new](https://discourse.threejs.org/u/new)\
**Post date:** [October 24, 2023, 1:26am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/1 "2023-10-24T01:26:38Z")

</div>

In my app I am using React with vanilla ThreeJS. Recently I made a mistake and placed the following code in the react component itself instead of placing it in the effect:

```javascript
let renderTarget = undefined;
  if (WebGL.isWebGL2Available()) {
    const size = renderer.getDrawingBufferSize(new THREE.Vector2());
    renderTarget = new THREE.WebGLRenderTarget(size.width, size.height, {
      samples: 8,
    });
  }
  const composer = new EffectComposer(renderer, renderTarget);

```

As a result, this code was executed every time when component re-rendered, which was especially frequent when I tried to resize the window for testing.

After some time the app started temporarily crashing saying that: `WebGLRenderer: Context lost.`, but it was also writing a lot of warnings like this: `WARNING: Too many active WebGL contexts. Oldest context will be lost.`. This particular warning was published when checking the availability of context here:

```javascript
if (WebGL.isWebGL2Available())

```

Under the hood this function looks following:

```javascript
static isWebGLAvailable() {
		try {
			const canvas = document.createElement( 'canvas' );
			return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) );
		} catch ( e ) {
			return false;
		}
	}

```

It creates the canvas every time it is called, which doesn’t look like the most elegant thing to do considering that it crashes the renderer. So my question is, wouldn’t it be better to create the same function that takes canvas as parameter instead of creating one each time it is called?

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [October 24, 2023, 2:31am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/2 "2023-10-24T02:31:16Z")

</div>

Do you need to call isWebGLAvailable more than once?

---

<div class="post-metadata">

**Author:** ![new](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/new/32/25580_2.png) [@new](https://discourse.threejs.org/u/new)\
**Post date:** [October 24, 2023, 2:42am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/3 "2023-10-24T02:42:44Z")

</div>

As I explained, no - I don’t. But it doesn’t make the utility function better.

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [October 24, 2023, 11:47am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/4 "2023-10-24T11:47:48Z")

</div>

I don’t think you need to recreate rendertargets on resize. They have a setSize method you can use for resizing. But if you do want to recreate it, you can/should call .dispose() on the old one first.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [October 24, 2023, 11:55am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/5 "2023-10-24T11:55:23Z")

</div>

document.createElement( ‘canvas’ ) is limited, you can only call it x times and the browser will crash. it’s because of the arbitrary limit that browsers set. you need to call it once globally, get the result and use that.

i wonder though, you are shooting yourself in the foot using react plain with three, instead of fiber. there is an entire eco system for three + react, it is larger than anything that exists in vanilla three. even your issue has been figured out [https://github.com/pmndrs/three-stdlib/blob/89d7e63589d8e09879fd1737160b93e9f81c6389/src/misc/WebGL.ts](https://github.com/pmndrs/three-stdlib/blob/89d7e63589d8e09879fd1737160b93e9f81c6389/src/misc/WebGL.ts) three-stdlib is a pmndrs managed fork of three/examples/jsm with better stability and fixed anti patterns. isWebGL2Available is one of hundreds of things that will cause issues in functional programming.

but either way, the fix is

```jsx
import { isWebGL2Available } from 'three-stdlib'

```

i would recommend you pull every jsm construct from stdlib as well.

---

<div class="post-metadata">

**Author:** ![new](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/new/32/25580_2.png) [@new](https://discourse.threejs.org/u/new)\
**Post date:** [October 24, 2023, 1:39pm UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/6 "2023-10-24T13:39:27Z")

</div>

Thank you very much. I can’t use `react-fiber` because I have my own AR framework integrated into a 3D viewer with seamless switch between them. `React-fiber` doesn’t cover my requirements there, or maybe my knowledge of it isn’t sufficient.

As for the function. As I explained, I have no intention to use this function more than once, multiple calls were bug which is already fixed. My point was related to the function itself. Even if I call it once, why do I need an extra canvas to be created? It is just waste that results in a crash if not used as intended. Not the best coding style and I am surprised to see things like that in ThreeJS.

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [October 24, 2023, 7:14pm UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/7 "2023-10-24T19:14:34Z")

</div>

> <https://stackoverflow.com/questions/54401577/check-if-webgl2-is-supported-and-enabled-in-clients-browser>

---

<div class="post-metadata">

**Author:** ![new](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/new/32/25580_2.png) [@new](https://discourse.threejs.org/u/new)\
**Post date:** [October 26, 2023, 12:57am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/8 "2023-10-26T00:57:23Z")

</div>

In order to create a new instance of EffectComposer you have to pass WebGLRenderer as a parameter, which means that the renderer has to be created in advance. The renderer does have a canvas element in it. So, why can’t we check the context using the existing rendering canvas instead of creating one every time? Something like this:

```javascript
static isWebGLAvailable(renderer: WebGLRenderer) {
		try {
			return !!(
        window.WebGLRenderingContext &&
        (renderer.domElement.getContext('webgl') ||
          renderer.domElement.getContext('experimental-webgl'))
      );
		} catch ( e ) {
			return false;
		}
	}

```

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [October 26, 2023, 4:32am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/9 "2023-10-26T04:32:27Z")

</div>

Getting a context a second time after the first one is gotten, destroys the first context.

WebGL is available on all the browsers but opera mini.

> **[WebGL - 3D Canvas graphics | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/webgl)**
>
> "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.

WebGL/WebGL2 is available on all the browsers ^ but opera mini and IE 11.

> **[WebGL 2.0 | Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/webgl2)**
>
> "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.

If you create your renderer without checking webGLAvailable first… it will throw an exception that you can catch.

try{  
renderer = new THREE.WebGLRenderer()  
}  
catch( error ){  
console.error( “WebGL is broken or unavailable:”, error)  
}

Using the isWebGLAvailable shim is really not a big deal. I know it seems inefficient but it’s really just a blip.

And if you don’t use it, and instead just try to create your renderer, you can see what errors it may throw here:

> <https://github.com/mrdoob/three.js/blob/181e04eea8b569dc09048f9dc644310ed6b745a6/src/renderers/WebGLRenderer.js#L259>

---

<div class="post-metadata">

**Author:** ![new](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/new/32/25580_2.png) [@new](https://discourse.threejs.org/u/new)\
**Post date:** [October 26, 2023, 3:01pm UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/10 "2023-10-26T15:01:04Z")

</div>

Got it! Thank you very much for the explanation.

---

<div class="post-metadata">

**Author:** ![oldboy](https://avatars.discourse-cdn.com/v4/letter/o/aca169/32.png) [@oldboy](https://discourse.threejs.org/u/oldboy)\
**Post date:** [January 20, 2024, 2:19am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/11 "2024-01-20T02:19:45Z")

</div>

> [@new](#):
>
> `nt`

hey @manthrax or anybody else who might know the answer, what value is returned by the `.isWebGLAvailable()` method, a boolean `true` or `false` value? Where can I find information about this particular method?

also, what does the `THREE.WebGL.getWebGLErrorMessage()` in `if (WebGL.isWebGLAvailable()) {...} else { THREE.WebGL.getWebGLErrorMessage() }` return?

thanks in advance!

(im looking at WebGL.js via dev tools now, so i should be able to figure this out on my own – actually, its still not clear to me what exactly `e` returns in the `catch` block (which errors? as strings? or what?))

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [January 20, 2024, 2:40am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/12 "2024-01-20T02:40:57Z")

</div>

It returns a bool.  
The whole detector isn’t super complex:

> <https://github.com/mrdoob/three.js/blob/668968e67c416b925abc5c68e1d3273651a5ac6d/examples/jsm/capabilities/WebGL.js#L1>

---

<div class="post-metadata">

**Author:** ![oldboy](https://avatars.discourse-cdn.com/v4/letter/o/aca169/32.png) [@oldboy](https://discourse.threejs.org/u/oldboy)\
**Post date:** [January 20, 2024, 2:46am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/13 "2024-01-20T02:46:00Z")

</div>

i shouldve been more specific. in the code below, id like to know what `error` is or returns.

```javascript
if (WebGL.isWebGLAvailable()){
  ...
} else {
  const error = THREE.WebGL.getWebGLErrorMessage()
}

```

i know it executes the code below.

```javascript
static getWebGLErrorMessage() {

  return this.getErrorMessage( 1 );

}

```

but what the heck does `this.getErrorMessage( 1 )` return?

never mind, found it below. it returns a `div` element with following `innerHTML`, `'Your $0 does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">$1</a>'`.

@manthrax

nonetheless, my code in the `if` block is quite extensive because ive put basically everything to do with WebGL inside of it, so im also wondering if i can place an `if (!WebGL.isWebGLAvailable()) throw new Error('end script due to error')` statement at the very top instead

thanks for ur responses \<3

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [January 20, 2024, 9:26am UTC](https://discourse.threejs.org/t/webgl-iswebgl2available-crashes-renderer/57335/14 "2024-01-20T09:26:20Z")

</div>

Yeah you could throw an exception… that’s a fine way to bail out imo.
