{"record":{"id":"82c2d1405366bcda","repo":"BabylonJS/Babylon.js","slug":"cannot-upload-to-a-2d-array-texture-that-has-no-in","errorCode":null,"errorMessage":"Cannot upload to a 2D array texture that has no internal texture.","messagePattern":"Cannot upload to a 2D array texture that has no internal texture\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts","lineNumber":57,"sourceCode":"    samplingMode?: number;\r\n    /** Defines the texture type (Constants.TEXTURETYPE_UNSIGNED_BYTE by default) */\r\n    textureType?: number;\r\n    /** Options forwarded to createImageBitmap when decoding each url */\r\n    imageBitmapOptions?: ImageBitmapOptions;\r\n}\r\n\r\n/**\r\n * Uploads a decoded image source (ImageBitmap, canvas, video, image element...) into a single layer of a 2D array texture.\r\n * This is the image-source counterpart to RawTexture2DArray.update, which only accepts raw bytes.\r\n * @param texture defines the 2D array texture to upload into\r\n * @param source defines the image source to upload\r\n * @param layer defines the array layer to upload into\r\n * @param options defines optional upload settings (invertY, premultiplyAlpha)\r\n */\r\nexport function UploadImageToTexture2DArrayLayer(texture: RawTexture2DArray, source: ImageSource, layer: number, options?: IUploadImageToTexture2DArrayLayerOptions): void {\r\n    const internalTexture = texture.getInternalTexture();\r\n    if (!internalTexture) {\r\n        throw new Error(\"Cannot upload to a 2D array texture that has no internal texture.\");\r\n    }\r\n\r\n    if (!Number.isInteger(layer) || layer < 0 || layer >= texture.depth) {\r\n        throw new Error(`Layer ${layer} is out of range for a 2D array texture with ${texture.depth} layers.`);\r\n    }\r\n\r\n    const scene = texture.getScene();\r\n    if (!scene) {\r\n        throw new Error(\"Cannot upload to a 2D array texture that is not attached to a scene.\");\r\n    }\r\n\r\n    const engine = scene.getEngine();\r\n    // updateTextureArrayLayerFromImageSource is an opt-in engine extension. When the consumer never\r\n    // imported it, the augmented method is missing, so fail early with the standard side-effect import\r\n    // message (matching the engine.rawTexture family) instead of a generic \"is not a function\" error.\r\n    if (!_IsSideEffectImplemented(engine.updateTextureArrayLayerFromImageSource)) {\r\n        throw _WarnImport(\"engine.texture2DArrayImageSource\");\r\n    }\r","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts#L39-L75","documentation":"UploadImageToTexture2DArrayLayer uploads an image source into one layer of a RawTexture2DArray via its underlying InternalTexture. If the array texture has not been given GPU storage yet (no internal texture), there is nothing to upload into, so the call throws.","triggerScenarios":"Calling UploadImageToTexture2DArrayLayer (or LoadImageToTexture2DArrayLayerAsync / CreateTexture2DArrayFromImageUrlsAsync) on a RawTexture2DArray constructed without dimensions or whose internal texture was never created/disposed.","commonSituations":"Creating the array texture with a factory that defers allocation, calling upload after texture.dispose(), or a failed creation path that left the wrapper without an internal texture.","solutions":["Create the RawTexture2DArray with valid width/height/depth so an internal texture is allocated before uploading","Check texture.getInternalTexture() is non-null before uploading","Ensure the texture has not been disposed before uploading","Recreate the texture if it was disposed"],"exampleFix":"// before\nconst tex = new RawTexture2DArray(null, 0, 0, 4, Constants.TEXTUREFORMAT_RGBA, scene);\nUploadImageToTexture2DArrayLayer(tex, bitmap, 0);\n// after\nconst tex = new RawTexture2DArray(data, width, height, layerCount, Constants.TEXTUREFORMAT_RGBA, scene);\ntex.createInt8ArrayTextureIfNeeded?.() ?? tex.getInternalTexture();\nUploadImageToTexture2DArrayLayer(tex, bitmap, 0);","handlingStrategy":"validation","validationCode":"if (!texture.getInternalTexture()) {\n  throw new Error(\"Texture has no internal texture; create it with valid dimensions first\");\n}\nUploadImageToTexture2DArrayLayer(texture, source, layer);","typeGuard":"function isUploadable(t: RawTexture2DArray): boolean {\n  return t.getInternalTexture() !== null && !t.isDisposed();\n}","tryCatchPattern":"try {\n  UploadImageToTexture2DArrayLayer(texture, bitmap, 0);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"no internal texture\")) {\n    recreateTextureAndRetry();\n  } else throw e;\n}","preventionTips":["Always create RawTexture2DArray with concrete width/height/depth","Check getInternalTexture() before GPU uploads","Do not upload to disposed textures"],"tags":["texture","gpu-resource","lifecycle"],"backgroundTag":"texture-not-initialized","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}