mrdoob/three.js · error

THREE.CameraHelper.update(): Invalid coordinate system: ${th

Error message

THREE.CameraHelper.update(): Invalid coordinate system: ${this.camera.coordinateSystem}

What it means

Thrown by CameraHelper.update() when the camera being visualized has a coordinateSystem that is neither WebGLCoordinateSystem nor WebGPUCoordinateSystem. The helper picks nearZ/farZ clip-space values (e.g. -1..1 for WebGL, 0..1 for WebGPU) to draw the frustum correctly; without a recognized system the helper cannot place those points.

Source

Thrown at src/helpers/CameraHelper.js:264

			nearZ = 1;
			farZ = 0;

		} else {

			if ( this.camera.coordinateSystem === WebGLCoordinateSystem ) {

				nearZ = - 1;
				farZ = 1;

			} else if ( this.camera.coordinateSystem === WebGPUCoordinateSystem ) {

				nearZ = 0;
				farZ = 1;

			} else {

				throw new Error( 'THREE.CameraHelper.update(): Invalid coordinate system: ' + this.camera.coordinateSystem );

			}

		}


		// center / target
		setPoint( 'c', pointMap, geometry, _camera, 0, 0, nearZ );
		setPoint( 't', pointMap, geometry, _camera, 0, 0, farZ );

		// near

		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, nearZ );
		setPoint( 'n2', pointMap, geometry, _camera, w, - h, nearZ );
		setPoint( 'n3', pointMap, geometry, _camera, - w, h, nearZ );
		setPoint( 'n4', pointMap, geometry, _camera, w, h, nearZ );

		// far

View on GitHub (pinned to da05705fa3)

Solutions

  1. Ensure the camera's coordinateSystem is set to a valid constant before constructing/updating CameraHelper: camera.coordinateSystem = THREE.WebGLCoordinateSystem (or WebGPUCoordinateSystem).
  2. Run the camera through a standard renderer at least once so its coordinateSystem is populated, then create the CameraHelper.
  3. If you built a custom camera class, expose and set coordinateSystem explicitly.
  4. Match the camera's coordinateSystem to whatever renderer/projection convention you actually use.

Example fix

// before: bare camera, coordinateSystem is null
const helper = new THREE.CameraHelper(cam);

// after: set the coordinate system explicitly
cam.coordinateSystem = THREE.WebGLCoordinateSystem;
const helper = new THREE.CameraHelper(cam);
Defensive patterns

Strategy: validation

Validate before calling

import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from 'three';

function ensureCameraCoordinateSystem(camera, fallback = WebGLCoordinateSystem) {
  const cs = camera.coordinateSystem;
  if (cs !== WebGLCoordinateSystem && cs !== WebGPUCoordinateSystem) {
    camera.coordinateSystem = fallback;
  }
  return camera;
}

ensureCameraCoordinateSystem(cam);
const helper = new THREE.CameraHelper(cam);

Type guard

function hasValidCoordinateSystem(camera) {
  const cs = camera && camera.coordinateSystem;
  return cs === THREE.WebGLCoordinateSystem || cs === THREE.WebGPUCoordinateSystem;
}

Prevention

When it happens

Trigger: Constructing new THREE.CameraHelper(camera) where camera.coordinateSystem is null/undefined or a custom value, then the helper runs its update. Using a Camera subclass whose coordinateSystem was never set by a renderer. Passing a raw Camera (not a PerspectiveCamera produced alongside a renderer) whose coordinateSystem defaults to null.

Common situations: Inspecting a frustum for a camera that has never been used with a real renderer. Mixing a WebGPU projection matrix convention with a camera flagged as WebGL, or vice versa. Custom camera subclasses that don't propagate coordinateSystem.

Related errors


AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12). Data as JSON: /api/errors/03b4375864a541bd. Report an issue: GitHub.