BabylonJS/Babylon.js · error · Error

Cannot upload to a 2D array texture that has no internal tex

Error message

Cannot upload to a 2D array texture that has no internal texture.

What it means

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.

Source

Thrown at packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts:57

    samplingMode?: number;
    /** Defines the texture type (Constants.TEXTURETYPE_UNSIGNED_BYTE by default) */
    textureType?: number;
    /** Options forwarded to createImageBitmap when decoding each url */
    imageBitmapOptions?: ImageBitmapOptions;
}

/**
 * Uploads a decoded image source (ImageBitmap, canvas, video, image element...) into a single layer of a 2D array texture.
 * This is the image-source counterpart to RawTexture2DArray.update, which only accepts raw bytes.
 * @param texture defines the 2D array texture to upload into
 * @param source defines the image source to upload
 * @param layer defines the array layer to upload into
 * @param options defines optional upload settings (invertY, premultiplyAlpha)
 */
export function UploadImageToTexture2DArrayLayer(texture: RawTexture2DArray, source: ImageSource, layer: number, options?: IUploadImageToTexture2DArrayLayerOptions): void {
    const internalTexture = texture.getInternalTexture();
    if (!internalTexture) {
        throw new Error("Cannot upload to a 2D array texture that has no internal texture.");
    }

    if (!Number.isInteger(layer) || layer < 0 || layer >= texture.depth) {
        throw new Error(`Layer ${layer} is out of range for a 2D array texture with ${texture.depth} layers.`);
    }

    const scene = texture.getScene();
    if (!scene) {
        throw new Error("Cannot upload to a 2D array texture that is not attached to a scene.");
    }

    const engine = scene.getEngine();
    // updateTextureArrayLayerFromImageSource is an opt-in engine extension. When the consumer never
    // imported it, the augmented method is missing, so fail early with the standard side-effect import
    // message (matching the engine.rawTexture family) instead of a generic "is not a function" error.
    if (!_IsSideEffectImplemented(engine.updateTextureArrayLayerFromImageSource)) {
        throw _WarnImport("engine.texture2DArrayImageSource");
    }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Create the RawTexture2DArray with valid width/height/depth so an internal texture is allocated before uploading
  2. Check texture.getInternalTexture() is non-null before uploading
  3. Ensure the texture has not been disposed before uploading
  4. Recreate the texture if it was disposed

Example fix

// before
const tex = new RawTexture2DArray(null, 0, 0, 4, Constants.TEXTUREFORMAT_RGBA, scene);
UploadImageToTexture2DArrayLayer(tex, bitmap, 0);
// after
const tex = new RawTexture2DArray(data, width, height, layerCount, Constants.TEXTUREFORMAT_RGBA, scene);
tex.createInt8ArrayTextureIfNeeded?.() ?? tex.getInternalTexture();
UploadImageToTexture2DArrayLayer(tex, bitmap, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (!texture.getInternalTexture()) {
  throw new Error("Texture has no internal texture; create it with valid dimensions first");
}
UploadImageToTexture2DArrayLayer(texture, source, layer);

Type guard

function isUploadable(t: RawTexture2DArray): boolean {
  return t.getInternalTexture() !== null && !t.isDisposed();
}

Try / catch

try {
  UploadImageToTexture2DArrayLayer(texture, bitmap, 0);
} catch (e) {
  if (e instanceof Error && e.message.includes("no internal texture")) {
    recreateTextureAndRetry();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling UploadImageToTexture2DArrayLayer (or LoadImageToTexture2DArrayLayerAsync / CreateTexture2DArrayFromImageUrlsAsync) on a RawTexture2DArray constructed without dimensions or whose internal texture was never created/disposed.

Common situations: 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.

Related errors


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