moeru-ai/airi · warning
Camera is not perspective camera, type error!
Error message
Camera is not perspective camera, type error!
What it means
After awaiting the camera and renderer DOM element, the component requires cameraTres.value instanceof PerspectiveCamera. With any other camera type (e.g. an OrthographicCamera scene) it warns and returns, so controls.value is never created and the component silently does nothing. Pan/zoom/rotate are configured disabled anyway, but no OrbitControls instance exists at all after this early return.
Source
Thrown at packages/stage-ui-three/src/components/Controls/OrbitControls.vue:184
},
)
}
disposeControlsChange?.()
controls.value?.addEventListener('change', onChange)
disposeControlsChange = () => controls.value?.removeEventListener('change', onChange)
}
onMounted(async () => {
// wait until camera is not undefined
await until(() => cameraTres.value && renderer.domElement).toBeTruthy()
if (!cameraTres.value || !renderer.domElement) {
console.warn('Camera or Renderer initialisation failure!')
return
}
// Narrow down the camera's type
if (!(cameraTres.value instanceof PerspectiveCamera)) {
console.warn('Camera is not perspective camera, type error!')
return
}
camera.value = cameraTres.value as PerspectiveCamera
// Obtain orbitControl instance
controls.value = new OrbitControls(camera.value, renderer.domElement)
controls.value.enablePan = false
controls.value.enableZoom = false
controls.value.enableRotate = false
// Align to tresjs conventions
controls.value.mouseButtons = {
LEFT: MOUSE.ROTATE,
MIDDLE: MOUSE.DOLLY,
RIGHT: MOUSE.PAN,
}
controls.value.touches = {
ONE: TOUCH.ROTATE,
TWO: TOUCH.DOLLY_PAN,
}View on GitHub (pinned to 677329427f)
Solutions
- Ensure the scene renders with a PerspectiveCamera before this component mounts
- Extend the guard to support OrthographicCamera if your scene needs it
- Verify cameraTres resolves to the camera object, not a wrapper or group
- Null-check controls.value downstream — it stays undefined after the early return
Example fix
// before
if (!(cameraTres.value instanceof PerspectiveCamera)) {
console.warn('Camera is not perspective camera, type error!')
return
}
camera.value = cameraTres.value as PerspectiveCamera
// after: reuse the narrowed guard
if (!isPerspectiveCamera(cameraTres.value)) {
console.warn('Camera is not perspective camera, type error!')
return
}
camera.value = cameraTres.value // already narrowed, no cast needed Defensive patterns
Strategy: type-guard
Type guard
import { PerspectiveCamera } from 'three'
function isPerspectiveCamera(camera: unknown): camera is PerspectiveCamera {
return camera instanceof PerspectiveCamera
} Prevention
- Render the scene with a PerspectiveCamera before mounting OrbitControls
- If orthographic support is needed, extend the component rather than removing the guard
- Verify the camera ref resolves to the camera itself, not a wrapper or group
- Null-check controls.value downstream; it stays undefined after the early return
When it happens
Trigger: Scene camera is an OrthographicCamera (2D-style scene); the camera ref resolving to a non-camera object; dropping this component into a scene not built for perspective cameras.
Common situations: Reusing the OrbitControls component in an orthographic/2D scene; a TresJS scene where the camera slot is filled by a custom camera.
Related errors
- Camera or Renderer initialisation failure!
- Failed to load HDRI environment:
- VRM model loading failure!
- NO model src, cannot load VRM model.
- No VRM animation loaded
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/3240c7e77da28c57.
Report an issue: GitHub.