BabylonJS/Babylon.js · error · Error
FrameGraphVolumetricLightingTask "${this.name}": lightingVol
Error message
FrameGraphVolumetricLightingTask "${this.name}": lightingVolumeMesh is empty What it means
record() also validates that the lightingVolumeMesh input actually contains meshes. The FrameGraphMesh input exists (is not undefined) but its .meshes array is null or empty, so the task has nothing to render the lighting volume with and throws instead of recording a degenerate pass.
Source
Thrown at packages/dev/core/src/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.ts:240
public override isReady() {
return (
this._renderLightingVolumeMaterial.isReady() &&
this._clearLightingVolumeTextureTask.isReady() &&
this._renderLightingVolumeMaterial.isReady() &&
this._blendLightingVolumeTask.isReady()
);
}
public override getClassName(): string {
return "FrameGraphVolumetricLightingTask";
}
public record(skipCreationOfDisabledPasses = false) {
if (this.targetTexture === undefined || this.depthTexture === undefined || this.camera === undefined || this.lightingVolumeMesh === undefined || this.light === undefined) {
throw new Error(`FrameGraphVolumetricLightingTask "${this.name}": targetTexture, depthTexture, camera, lightingVolumeMesh and light are required`);
}
if (!this.lightingVolumeMesh.meshes || this.lightingVolumeMesh.meshes.length === 0) {
throw new Error(`FrameGraphVolumetricLightingTask "${this.name}": lightingVolumeMesh is empty`);
}
this._frameGraph.textureManager.resolveDanglingHandle(this.outputTexture, this.targetTexture);
const textureManager = this._frameGraph.textureManager;
let lightingVolumeTexture = this.lightingVolumeTexture;
if (!lightingVolumeTexture) {
const targetTextureCreationOptions = textureManager.getTextureCreationOptions(this.targetTexture);
targetTextureCreationOptions.options.labels = ["InScattering"];
targetTextureCreationOptions.options.samples = 1;
lightingVolumeTexture = textureManager.createRenderTargetTexture(`${this.name} - lighting volume texture`, targetTextureCreationOptions);
}
this.lightingVolumeMesh.meshes[0].material = this._renderLightingVolumeMaterial;
View on GitHub (pinned to 0592b347b8)
Solutions
- Make sure the source mesh (e.g. a bounding-box/cone mesh for the light volume) exists and is added to the mesh input before record().
- Check that the mesh wasn't disposed: verify mesh.isDisposed() === false and it's still in the scene.
- If meshes load asynchronously, wait for load completion (e.g. onReady / await) before building the frame graph.
- Validate input.meshes.length > 0 before calling record() and skip or error out gracefully otherwise.
Example fix
// before
const meshInput = frameGraph.createMeshInputValue([]);
task.lightingVolumeMesh = meshInput;
task.record(); // throws: lightingVolumeMesh is empty
// after
const volumeMesh = MeshBuilder.CreateBox("vol", { size: 1 }, scene);
const meshInput = frameGraph.createMeshInputValue(volumeMesh);
task.lightingVolumeMesh = meshInput;
task.record(); Defensive patterns
Strategy: validation
Validate before calling
if (!task.lightingVolumeMesh || !task.lightingVolumeMesh.meshes || task.lightingVolumeMesh.meshes.length === 0) {
throw new Error("lightingVolumeMesh input has no meshes");
}
task.record(); Type guard
function hasMeshes(input: { meshes?: unknown[] } | undefined): input is { meshes: unknown[] } {
return !!input && Array.isArray(input.meshes) && input.meshes.length > 0;
} Try / catch
try {
task.record();
} catch (e) {
if ((e as Error).message.includes("lightingVolumeMesh is empty")) {
console.error("Volume mesh empty or disposed; re-binding mesh input.");
task.lightingVolumeMesh = frameGraph.createMeshInputValue(volumeMesh);
task.record();
} else throw e;
} Prevention
- Bind the volume mesh only after it is created and added to the scene.
- Don't dispose meshes referenced by frame graph inputs until the graph is torn down.
- Wait for async mesh loading to finish before building the graph.
- Assert input.meshes.length > 0 in dev builds before record().
When it happens
Trigger: Calling record() when this.lightingVolumeMesh.meshes is undefined or has length 0 — e.g. a mesh input created from an empty container, a mesh removed from the scene after the input was created, or an input handle bound to nothing.
Common situations: Passing an AssetContainer's meshes array after it was emptied/disposed; the volume mesh was disposed before frame graph build; filtering scene meshes produced an empty list; async mesh loading hadn't finished when the graph was built.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- FrameGraphVolumetricLightingTask "${this.name}": targetTextu
- FrameGraphCascadedShadowGeneratorTask ${this.name}: light, o
- FrameGraphObjectRendererTask ${this.name}: targetTexture, ob
- At least one mesh is needed to create the nav mesh.
- FrameGraphHighlightLayerTask "${this.name}": objectRendererT
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/c8c6411f119c8029.
Report an issue: GitHub.