BabylonJS/Babylon.js · error

updateWrappedNativeTexture: new handle dimensions (${newWidt

Error message

updateWrappedNativeTexture: new handle dimensions (${newWidth}x${newHeight}) must match the wrapped texture's dimensions (${internalTexture.baseWidth}x${internalTexture.baseHeight}).

What it means

updateWrappedNativeTexture requires the new native texture handle to have exactly the same dimensions as the wrapped InternalTexture (baseWidth/baseHeight), because bgfx framebuffers and engine caches bake the size into state that is not rebuilt here.

Source

Thrown at packages/dev/core/src/Engines/thinNativeEngine.pure.ts:2164

     * texture and call {@link wrapNativeTexture} again. Sampling mode and mip-map flag are properties of the logical
     * wrapped texture and are re-applied to the new resource. Any render-target wrapper holding this texture as its
     * color attachment has its framebuffer rebuilt with the new handle.
     *
     * Throws if the target was not produced by {@link wrapNativeTexture}, if the new handle's dimensions don't match,
     * if the wrapped texture is part of a multi render-target, or if the wrapper has a depth/stencil texture (these
     * are not supported in this version; dispose and re-wrap).
     * @param internalTexture defines the wrapped InternalTexture to repoint
     * @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;
            }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Dispose the wrapped texture and call wrapNativeTexture again with the new handle and its actual dimensions.
  2. Recreate the new native texture at the original dimensions before updating.
  3. Update dependent render targets and viewport state after recreating at the new size.

Example fix

// before
engine.updateWrappedNativeTexture(wrapped, resizedNativeTex); // throws on size mismatch

// after
wrapped.dispose();
const wrapped2 = engine.wrapNativeTexture(resizedNativeTex, newW, newH, ...);
Defensive patterns

Strategy: validation

Validate before calling

const w = engine._engine.getTextureWidth(newNativeTex);
const h = engine._engine.getTextureHeight(newNativeTex);
if (w !== wrapped.baseWidth || h !== wrapped.baseHeight) {
  throw new Error(`Resize mismatch: ${w}x${h} vs ${wrapped.baseWidth}x${wrapped.baseHeight}; dispose and re-wrap.`);
}

Try / catch

try {
  engine.updateWrappedNativeTexture(wrapped, newNativeTex);
} catch (e) {
  if (e.message.includes("dimensions")) {
    wrapped.dispose();
    wrapped = engine.wrapNativeTexture(newNativeTex, newW, newH, sampling, ...);
  } else throw e;
}

Prevention

When it happens

Trigger: engine.updateWrappedNativeTexture(wrapped, newNativeTex) where engine._engine.getTextureWidth/Height(newNativeTex) differ from wrapped.baseWidth/baseHeight, e.g. after resizing an offscreen render target.

Common situations: Window/resize events recreate a native texture at a new resolution and the caller tries to swap it into the existing wrapped texture instead of disposing and re-wrapping at the new size.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/260b8fd7c429a8d6. Report an issue: GitHub.