BabylonJS/Babylon.js · error · Error
To call addPart()/addParts(), each source mesh must not be a
Error message
To call addPart()/addParts(), each source mesh must not be a compound
What it means
The same addPart/addParts validation loop also rejects compound sources: if `other.isCompound` is true the mesh already consists of merged parts and cannot itself be added as a part. This prevents nested/flattened compound hierarchies.
Source
Thrown at packages/dev/core/src/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.ts:1131
*
* @param others - Source meshes to append (must each be non-compound and fully loaded)
* @param disposeOthers - Dispose source meshes after appending
* @returns Proxy meshes and their assigned part indices
*/
protected _addPartsInternal(others: IGaussianSplattingPartSource[], disposeOthers: boolean): { proxyMeshes: GaussianSplattingPartProxyMesh[]; assignedPartIndices: number[] } {
if (others.length === 0) {
return { proxyMeshes: [], assignedPartIndices: [] };
}
// Validate
for (const other of others) {
// Reserved-empty placeholders (reserveStreamingPart) intentionally carry no splat data —
// their atlas region is left zeroed (invisible) for a streaming engine to decode into later.
if (!other._splatsData && !other._isReservedEmpty) {
throw new Error(`To call addPart()/addParts(), each source mesh must be fully loaded`);
}
if (other.isCompound) {
throw new Error(`To call addPart()/addParts(), each source mesh must not be a compound`);
}
}
const splatCountA = this._vertexCount;
const totalOtherCount = others.reduce((s, o) => s + o._vertexCount, 0);
const totalCount = splatCountA + totalOtherCount;
const textureSize = this._getTextureSize(totalCount);
const textureLength = textureSize.x * textureSize.y;
const covBSItemSize = this._useRGBACovariants ? 4 : 2;
// Allocate destination arrays for the full new texture
const covA = new Uint16Array(textureLength * 4);
const covB = new Uint16Array(covBSItemSize * textureLength);
const colorArray = new Uint8Array(textureLength * 4);
// Merged SH degree. The compound carries SH if any existing or new part has it, or a hosted stream bakes it.
// Parts without SH get neutral (128) fill. `_streamingShDegree` is the degree of the live SH streams (recomputed
View on GitHub (pinned to 0592b347b8)
Solutions
- Only add non-compound (single-part) splat meshes; keep the original individual meshes and merge those instead of the compound.
- Check `other.isCompound` before merging and skip/reject those meshes.
- Restructure to merge all leaves in a single addParts call rather than iteratively merging compounds.
Example fix
// before const ab = a.addParts([b]); // ab.isCompound === true ab.addParts([c]); // throws // after a.addParts([b, c]); // merge all sources in one call
Defensive patterns
Strategy: validation
Validate before calling
if (other.isCompound) {
throw new SkipSource("compound meshes cannot be parts");
}
compound.addParts([other]); Type guard
function isNonCompoundSource(mesh: GaussianSplattingMeshBase): boolean {
return !mesh.isCompound;
} Try / catch
try {
compound.addParts(sources);
} catch (e) {
if (e instanceof Error && e.message.includes("not be a compound")) {
Logger.Warn("Merge leaves instead of compounds");
return null;
}
throw e;
} Prevention
- Merge all leaf splat meshes in a single addParts call; never chain merges of compounds
- Keep references to original leaf meshes for later merges
- Check isCompound on every source before merging
- Never pass a compound back into addPart/addParts, including itself
When it happens
Trigger: Calling `a.addParts([b])` where `b` was previously built via `addPart`/`addParts` (isCompound === true), or passing the result of a previous compound merge as a source.
Common situations: Chaining merges (merge A+B, then merge result with C); reusing an already-merged mesh as a source in another scene's compound; accidentally adding a compound to itself or a sibling compound.
Related errors
- GaussianSplattingDebugger.addMesh: mesh must have a Gaussian
- To call addPart()/addParts(), each source mesh must be fully
- Cannot add part, as the maximum part count (${maxPartCount})
- Cannot rebuild compound part "${proxy.name}": the retained c
- reserveStreamingPart: shTextureCount ${shTextureCount} does
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/46faaf770f276a0a.
Report an issue: GitHub.