BabylonJS/Babylon.js · error
updateWrappedNativeTexture: new handle layer count (${newLay
Error message
updateWrappedNativeTexture: new handle layer count (${newLayerCount}) must match the wrapped texture's layer count (${oldLayerCount}). What it means
updateWrappedNativeTexture validates layer counts: if the wrapped texture is a 2D array its depth is compared against the new handle's layer count (via getTextureLayerCount); for non-array textures the expected count is 1. A mismatch throws because repointing would silently change the texture's effective layering.
Source
Thrown at packages/dev/core/src/Engines/thinNativeEngine.pure.ts:2172
* @param texture defines the new native texture handle to wrap
*/
public updateWrappedNativeTexture(internalTexture: InternalTexture, texture: NativeTexture): void {
if (internalTexture.source !== InternalTextureSource.External) {
throw new Error("updateWrappedNativeTexture: target InternalTexture was not produced by wrapNativeTexture.");
}
const newWidth = this._engine.getTextureWidth(texture);
const newHeight = this._engine.getTextureHeight(texture);
if (newWidth !== internalTexture.baseWidth || newHeight !== internalTexture.baseHeight) {
throw new Error(
`updateWrappedNativeTexture: new handle dimensions (${newWidth}x${newHeight}) must match the wrapped texture's dimensions (${internalTexture.baseWidth}x${internalTexture.baseHeight}).`
);
}
if (this._engine.getTextureLayerCount) {
const newLayerCount = this._engine.getTextureLayerCount(texture);
const oldLayerCount = internalTexture.is2DArray ? internalTexture.depth : 1;
if (newLayerCount !== oldLayerCount) {
throw new Error(`updateWrappedNativeTexture: new handle layer count (${newLayerCount}) must match the wrapped texture's layer count (${oldLayerCount}).`);
}
}
// Pre-validate before mutating any state so a thrown precondition leaves the InternalTexture untouched.
// Note: rtWrapper.texture only returns _textures[0]; walk every attachment to catch the multi-RT case where
// the wrapped texture is at index > 0.
for (const rtWrapper of this._renderTargetWrapperCache) {
if (!rtWrapper.textures?.includes(internalTexture)) {
continue;
}
if (rtWrapper.isMulti) {
throw new Error("updateWrappedNativeTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.");
}
if (rtWrapper._depthStencilTexture) {
// After a DisableRendering / EnableRendering cycle the bgfx framebuffer + the depth/stencil texture's
// bgfx handle are both stale. Rebuilding the depth/stencil texture from the wrapper's stored settings
// is feasible but non-trivial; v1 rejects and asks the caller to dispose + re-wrap.
throw new Error("updateWrappedNativeTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported. Dispose and re-wrap.");
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure the replacement native texture is created with the same layer count (same array size/cube structure).
- Dispose and re-wrap via wrapNativeTexture when the layer structure genuinely changes.
- Skip the update path entirely for array textures and recreate dependent pipelines/framebuffers instead.
Example fix
// before
engine.updateWrappedNativeTexture(wrappedArray, singleLayerTex);
// after
const newWrapped = engine.wrapNativeTexture(arrayTex, w, h, { layers: oldDepth }); Defensive patterns
Strategy: validation
Validate before calling
const newLayers = engine._engine.getTextureLayerCount?.(newNativeTex) ?? 1;
const expectedLayers = wrapped.is2DArray ? wrapped.depth : 1;
if (newLayers !== expectedLayers) throw new Error(`Layer count mismatch: ${newLayers} vs ${expectedLayers}`); Try / catch
try {
engine.updateWrappedNativeTexture(wrapped, newNativeTex);
} catch (e) {
if (e.message.includes("layer count")) {
wrapped.dispose();
wrapped = engine.wrapNativeTexture(newNativeTex, w, h, sampling, ...);
} else throw e;
} Prevention
- Avoid texture arrays entirely on Babylon Native (also rejected by createRawTexture).
- Match cube/array structure when creating replacement native textures.
- Document layer-count invariants wherever native handles are exchanged between systems.
When it happens
Trigger: Swapping in a native texture handle whose layer/array-layer count differs from the wrapped texture (e.g. replacing a 6-layer array or cube-derived handle with a single-layer texture, or vice versa).
Common situations: Exchanging a texture array between passes with different layer counts; wrapping cube/2D-array textures then updating with a plain 2D handle.
Related errors
- updateWrappedNativeTexture: target InternalTexture was not p
- updateWrappedNativeTexture: new handle dimensions (${newWidt
- updateWrappedNativeTexture: wrapped texture is part of a mul
- updateWrappedNativeTexture: wrapped texture's render-target
- updateWrappedWebGLTexture: target InternalTexture was not pr
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/f0c776faef3bd420.
Report an issue: GitHub.