{"record":{"id":"5c1414318340531f","repo":"BabylonJS/Babylon.js","slug":"updatewrappedwebgltexture-target-internaltexture","errorCode":null,"errorMessage":"updateWrappedWebGLTexture: target InternalTexture was not produced by wrapWebGLTexture.","messagePattern":"updateWrappedWebGLTexture: target InternalTexture was not produced by wrapWebGLTexture\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/engine.pure.ts","lineNumber":815,"sourceCode":"     * references held by materials, render-target wrappers, particle systems, etc.\r\n     *\r\n     * The new handle must describe a texture with the same dimensions the wrapped texture was created with. A WebGL\r\n     * handle is opaque (the dimensions can't be introspected), so we can't validate this -- passing a mismatched\r\n     * handle is undefined behaviour. Sampling mode and mip-map flag are properties of the logical wrapped texture and\r\n     * are re-applied to the new resource. Any render-target wrapper holding this texture as its color attachment has\r\n     * its framebuffer rebuilt with the new handle (including a fresh depth/stencil renderbuffer, since the old one\r\n     * came from the dead context). If the wrapper is multisampled, the MSAA framebuffer + color renderbuffer + MSAA\r\n     * depth/stencil buffer are rebuilt too.\r\n     *\r\n     * Throws if the target was not produced by {@link wrapWebGLTexture}, if the wrapped texture is part of a multi\r\n     * render-target wrapper, or if the wrapper has a depth/stencil texture (these are not supported in this version;\r\n     * dispose and re-wrap).\r\n     * @param internalTexture defines the wrapped InternalTexture to repoint\r\n     * @param texture defines the new WebGL handle to wrap\r\n     */\r\n    public updateWrappedWebGLTexture(internalTexture: InternalTexture, texture: WebGLTexture): void {\r\n        if (internalTexture.source !== InternalTextureSource.External) {\r\n            throw new Error(\"updateWrappedWebGLTexture: target InternalTexture was not produced by wrapWebGLTexture.\");\r\n        }\r\n\r\n        // Pre-validate before mutating any state so a thrown precondition leaves the InternalTexture untouched.\r\n        // Note: rtWrapper.texture only returns _textures[0]; walk every attachment to catch the multi-RT case where\r\n        // the wrapped texture is at index > 0.\r\n        for (const rtWrapper of this._renderTargetWrapperCache) {\r\n            if (!rtWrapper.textures?.includes(internalTexture)) {\r\n                continue;\r\n            }\r\n            if (rtWrapper.isMulti) {\r\n                throw new Error(\"updateWrappedWebGLTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.\");\r\n            }\r\n            if (rtWrapper._depthStencilTexture) {\r\n                // The depth/stencil texture's GL handle was also lost on context restore. Rebuilding it from the\r\n                // wrapper's stored depth settings + re-attaching is feasible but non-trivial; v1 rejects and asks\r\n                // the caller to dispose + re-wrap (which also recreates the depth/stencil texture via the public API).\r\n                throw new Error(\"updateWrappedWebGLTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported. Dispose and re-wrap.\");\r\n            }\r","sourceCodeStart":797,"sourceCodeEnd":833,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/engine.pure.ts#L797-L833","documentation":"updateWrappedWebGLTexture re-points an InternalTexture previously produced by wrapWebGLTexture to a new WebGLTexture handle (typically after context restore). It validates internalTexture.source === InternalTextureSource.External; textures created normally (via createTexture, render targets, etc.) are not 'External' and cannot be re-wrapped, so Babylon throws to protect state.","triggerScenarios":"Calling engine.updateWrappedWebGLTexture(internalTexture, newWebGLTexture) with an InternalTexture that came from createTexture / render target / dynamic texture instead of wrapWebGLTexture.","commonSituations":"Context-restoration recovery code that iterates ALL engine textures instead of only wrapped ones; mixing wrapped and created textures in the same collection; using a texture from a render target wrapper by mistake.","solutions":["Only pass textures returned by engine.wrapWebGLTexture (source === InternalTextureSource.External)","Filter your texture list before restoring: skip textures whose source !== InternalTextureSource.External","For non-external textures, recreate them normally (reload from source) after context restore instead of re-wrapping","Track which textures you wrapped originally and restore only those"],"exampleFix":"// before\ntextures.forEach(t => engine.updateWrappedWebGLTexture(t, newHandle)); // throws for created textures\n// after\nimport { InternalTextureSource } from 'core/Materials/Textures/internalTexture';\ntextures.filter(t => t.source === InternalTextureSource.External)\n  .forEach(t => engine.updateWrappedWebGLTexture(t, newHandle));","handlingStrategy":"type-guard","validationCode":"import { InternalTextureSource } from 'core/Materials/Textures/internalTexture';\nif (internalTexture.source !== InternalTextureSource.External) {\n  throw new Error('Only textures from wrapWebGLTexture can be re-wrapped');\n}","typeGuard":"function isWrappedExternal(t: InternalTexture): boolean {\n  return t.source === InternalTextureSource.External;\n}","tryCatchPattern":"try {\n  engine.updateWrappedWebGLTexture(t, newHandle);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('not produced by wrapWebGLTexture')) {\n    t.dispose();\n    recreateTextureFromSource(t); // normal reload path for non-external textures\n  } else throw e;\n}","preventionTips":["Maintain a separate registry of wrapped textures at wrapWebGLTexture call time","Check internalTexture.source before any re-wrap logic","Recreate created textures via their original loader after context loss","Never pass render-target or dynamic textures to updateWrappedWebGLTexture"],"tags":["webgl","texture-wrapping","context-restore","validation"],"backgroundTag":"texture-not-externally-wrapped","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}