phaserjs/phaser · critical · Error

WebGL unsupported

Error message

WebGL unsupported

What it means

WebGLRenderer.js:716 throws after both `getContext('webgl', ...)` and the `experimental-webgl` fallback return null (or a freshly-lost context). The renderer cannot function without a GL context, so it marks `contextLost = true` and aborts construction.

Source

Thrown at src/renderer/webgl/WebGLRenderer.js:716

            this.spector.onCapture.add(this.onCapture.bind(this));
        }

        //  Did they provide their own context?
        if (game.config.context)
        {
            gl = game.config.context;
        }
        else
        {
            gl = canvas.getContext('webgl', config.contextCreation) || canvas.getContext('experimental-webgl', config.contextCreation);
        }

        if (!gl || gl.isContextLost())
        {
            this.contextLost = true;

            throw new Error('WebGL unsupported');
        }

        this.gl = gl;

        this.setExtensions();

        this.setContextHandlers();

        //  Set it back into the Game, so developers can access it from there too
        game.context = gl;

        for (var i = 0; i <= 27; i++)
        {
            this.blendModes.push(WebGLBlendParametersFactory.createCombined(this));
        }

        //  ADD
        this.blendModes[1].func = [ gl.ONE, gl.DST_ALPHA, gl.ONE, gl.DST_ALPHA ];

View on GitHub (pinned to 41be1e462b)

Solutions

  1. Fall back to Canvas: set `type: Phaser.AUTO` (Phaser picks Canvas when WebGL probe fails) or explicitly `Phaser.CANVAS`.
  2. For headless/CI, run with a software GL backend (Chrome `--use-gl=angle --use-angle=swiftshader-webgl`, or Xvfb + Mesa).
  3. Prompt the user to enable WebGL/hardware acceleration in their browser.
  4. Provide a `contextLostHandler` for graceful runtime recovery if the context dies later.

Example fix

// before
type: Phaser.WEBGL // fails on GPU-less host
// after
type: Phaser.AUTO
Defensive patterns

Strategy: fallback

Validate before calling

let gl
try {
  const c = document.createElement('canvas')
  gl = c.getContext('webgl') || c.getContext('experimental-webgl')
} catch { gl = null }
const type = gl ? Phaser.WEBGL : Phaser.CANVAS
const game = new Phaser.Game({ type, width: 800, height: 600 })

Type guard

const getContextOrThrow = () => {
  const c = document.createElement('canvas')
  const gl = c.getContext('webgl') || c.getContext('experimental-webgl')
  if (!gl || gl.isContextLost()) throw new Error('WebGL unsupported')
  return gl
}

Try / catch

try {
  game = new Phaser.Game({ type: Phaser.WEBGL, ... })
} catch (e) {
  if (/WebGL unsupported/.test(e.message)) {
    game = new Phaser.Game({ type: Phaser.CANVAS, ... })
  } else { throw e }
}

Prevention

When it happens

Trigger: Constructing a WebGLRenderer (via `type: Phaser.WEBGL` or AUTO-resolved-to-WebGL) where the canvas yields no GL context: GPU blacklisted by the browser, driver crash, disabled WebGL, or an environment without WebGL support. The `game.config.context` branch (a developer-supplied context) only bypasses this if non-null and not lost.

Common situations: CI/headless browsers without GPU; locked-down corporate machines where WebGL is disabled in about:flags; older mobile GPUs on the driver blocklist; the user disabled hardware acceleration in their browser settings.

Related errors


AI-assisted analysis of phaserjs/phaser@41be1e462b (2026-08-13). Data as JSON: /api/errors/c8f66d2e4ad2dd55. Report an issue: GitHub.