{"record":{"id":"2af041b80c9e49e9","repo":"BabylonJS/Babylon.js","slug":"updatewrappednativetexture-target-internaltexture","errorCode":null,"errorMessage":"updateWrappedNativeTexture: target InternalTexture was not produced by wrapNativeTexture.","messagePattern":"updateWrappedNativeTexture: target InternalTexture was not produced by wrapNativeTexture\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/thinNativeEngine.pure.ts","lineNumber":2158,"sourceCode":"     * Intended for the device-loss / device-restored flow (a DisableRendering / EnableRendering cycle from the host\r\n     * application): when the host recreates its external resource on the new graphics device, it calls this method to\r\n     * repoint Babylon's wrapper at the new handle without losing references held by materials, render-target wrappers,\r\n     * particle systems, etc.\r\n     *\r\n     * The new handle must match the wrapped texture's recorded dimensions. To change dimensions, dispose the wrapped\r\n     * texture and call {@link wrapNativeTexture} again. Sampling mode and mip-map flag are properties of the logical\r\n     * wrapped texture and are re-applied to the new resource. Any render-target wrapper holding this texture as its\r\n     * color attachment has its framebuffer rebuilt with the new handle.\r\n     *\r\n     * Throws if the target was not produced by {@link wrapNativeTexture}, if the new handle's dimensions don't match,\r\n     * if the wrapped texture is part of a multi render-target, or if the wrapper has a depth/stencil texture (these\r\n     * are not supported in this version; dispose and re-wrap).\r\n     * @param internalTexture defines the wrapped InternalTexture to repoint\r\n     * @param texture defines the new native texture handle to wrap\r\n     */\r\n    public updateWrappedNativeTexture(internalTexture: InternalTexture, texture: NativeTexture): void {\r\n        if (internalTexture.source !== InternalTextureSource.External) {\r\n            throw new Error(\"updateWrappedNativeTexture: target InternalTexture was not produced by wrapNativeTexture.\");\r\n        }\r\n\r\n        const newWidth = this._engine.getTextureWidth(texture);\r\n        const newHeight = this._engine.getTextureHeight(texture);\r\n        if (newWidth !== internalTexture.baseWidth || newHeight !== internalTexture.baseHeight) {\r\n            throw new Error(\r\n                `updateWrappedNativeTexture: new handle dimensions (${newWidth}x${newHeight}) must match the wrapped texture's dimensions (${internalTexture.baseWidth}x${internalTexture.baseHeight}).`\r\n            );\r\n        }\r\n        if (this._engine.getTextureLayerCount) {\r\n            const newLayerCount = this._engine.getTextureLayerCount(texture);\r\n            const oldLayerCount = internalTexture.is2DArray ? internalTexture.depth : 1;\r\n            if (newLayerCount !== oldLayerCount) {\r\n                throw new Error(`updateWrappedNativeTexture: new handle layer count (${newLayerCount}) must match the wrapped texture's layer count (${oldLayerCount}).`);\r\n            }\r\n        }\r\n\r\n        // Pre-validate before mutating any state so a thrown precondition leaves the InternalTexture untouched.\r","sourceCodeStart":2140,"sourceCodeEnd":2176,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/thinNativeEngine.pure.ts#L2140-L2176","documentation":"updateWrappedNativeTexture can only repoint an InternalTexture whose source is InternalTextureSource.External, i.e. one created by wrapNativeTexture. The guard exists because repointing a non-external texture would bypass ownership of its native handle and corrupt engine state.","triggerScenarios":"Calling engine.updateWrappedNativeTexture(internalTexture, nativeTexture) on a texture created via createTexture/createRawTexture or a render-target texture (source !== External).","commonSituations":"Keeping a plain created texture in a variable that also holds wrapped textures and passing the wrong one; assuming any InternalTexture can be updated.","solutions":["Only pass InternalTextures returned from engine.wrapNativeTexture().","If you need to swap the underlying data of a regular texture, recreate it (dispose + create) instead.","Track wrapped textures explicitly (e.g. keep the value returned by wrapNativeTexture) rather than reading texture from a render target."],"exampleFix":"// before\nengine.updateWrappedNativeTexture(rt.texture, newNativeTex); // rt texture is not wrapped\n\n// after\nconst wrapped = engine.wrapNativeTexture(oldNativeTex, width, height, ...);\nengine.updateWrappedNativeTexture(wrapped, newNativeTex);","handlingStrategy":"validation","validationCode":"if (internalTexture.source !== BABYLON.InternalTextureSource.External) {\n  throw new Error(\"updateWrappedNativeTexture requires a texture from wrapNativeTexture\");\n}","typeGuard":"const isWrappedNativeTexture = (t: BABYLON.InternalTexture): boolean =>\n  t.source === BABYLON.InternalTextureSource.External;","tryCatchPattern":"try {\n  engine.updateWrappedNativeTexture(tex, newNativeTex);\n} catch (e) {\n  if (e.message.includes(\"not produced by wrapNativeTexture\")) {\n    console.warn(\"Recreating texture instead of updating\", e);\n    recreateTexture(tex);\n  } else throw e;\n}","preventionTips":["Keep wrapNativeTexture return values in dedicated variables/types (e.g. WrappedNativeTexture).","Never pass render-target textures to updateWrappedNativeTexture.","Add an assertion helper in your renderer that checks source === External before swaps."],"tags":["native","texture-wrapping","invalid-argument"],"backgroundTag":"invalid-texture-handle","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}