# Regression in 8.47.2: TypeError: Cannot read properties of undefined (reading 'isRefractionEnabled') in babylonjs-loaders

**URL:** <https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253>\
**Category:** Bugs\
**Tags:** material, pbr\
**Created:** [January 29, 2026, 3:56am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253 "2026-01-29T03:56:09Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 29, 2026, 3:56am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/1 "2026-01-29T03:56:09Z")

</div>

**Environment**

- babylonjs / @babylonjs/core: 8.47.2

- babylonjs-loaders: 8.47.2

- Build: Vite 7, TypeScript 5.9

- Usage: import ‘babylonjs-loaders’ and SceneLoader.LoadAssetContainerAsync() for .glb assets

**What works**

- With 8.47.0 (core + loaders) the app runs and loads GLB containers without this error.

**What breaks**

- After upgrading to 8.47.2, at runtime we get:

`TypeError: Cannot read properties of undefined (reading 'isRefractionEnabled')`

The stack trace points into babylonjs-loaders (e.g. inside the loader code that reads something like` ... .isRefractionEnabled`), so some object the loader expects (e.g. material or refraction config) is undefined.

**Changelog**

- 8.47.2 only documents a Playground/Inspector v2 fix [1](https://github.com/BabylonJS/Babylon.js/pull/17747).

- 8.47.1 had Loaders/Inspector changes (e.g. “Inspector v2: GLTF Import tools”, “OpenPBR Translucent Slab”).

So the regression could have been introduced in 8.47.1 and only showed up after moving to 8.47.2, or be specific to 8.47.2’s bundle.

**Question**

- Is this a known regression (e.g. missing null check around refraction/PBR in the GLB loader)?

- If not, I can try to provide a minimal repro (small scene + one GLB and exact load sequence).

Thanks.

---

<div class="post-metadata">

**Author:** ![alexchuber](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/alexchuber/32/52000_2.png) [@alexchuber](https://forum.babylonjs.com/u/alexchuber)\
**Post date:** [January 29, 2026, 4:51am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/2 "2026-01-29T04:51:49Z")

</div>

Thanks for the report! Yes, if you could supply a minimal repro, that’d be great.

---

<div class="post-metadata">

**Author:** ![PirateJC](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/piratejc/32/1003_2.png) [@PirateJC](https://forum.babylonjs.com/u/PirateJC)\
**Post date:** [January 29, 2026, 5:19am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/3 "2026-01-29T05:19:30Z")

</div>

Yes! Thanks for flagging this @onekit !!! We’ll jump on this as soon as possible.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 29, 2026, 8:13am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/4 "2026-01-29T08:13:12Z")

</div>

A reproduction would help, as I have tried to reproduce the problem with different assets, but without success.

---

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 29, 2026, 3:29pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/5 "2026-01-29T15:29:47Z")

</div>

I’m working on it, but I haven’t been able to reproduce it yet.

The issue occurs when a **PBR** (or **Standard** ) material is assigned **before** the first frame. The loader’s observer triggers and attempts to read `engine.getCaps().isRefractionEnabled` . If `getCaps()` is still undefined at that point, the application crashes. This might not happen in the **Playground** because the first frame often executes before the material assignment.

A second scenario is similar: you preload a **GLB** , add the container to the scene, and then assign a new material to that preloaded mesh (e.g., replacing it with a `PBRMaterial`). The loader’s observer runs upon the material change and checks the same property. In the **Playground** , the `.then()` block usually executes after the first frame, meaning `getCaps()` is already initialized, which masks the error.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 29, 2026, 5:33pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/6 "2026-01-29T17:33:13Z")

</div>

> [@onekit](#):
>
> engine.getCaps().isRefractionEnabled

There’s no **isRefractionEnabled** property in the engine capabilities (?)

If you can’t repro in the playground, providing a live url could also work, as we will be able to put breakpoints and debug.

---

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 30, 2026, 6:07pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/7 "2026-01-30T18:07:38Z")

</div>

This text created with AI-assistant 😁, it recommend me to report it like this:

`TypeError: Cannot read properties of undefined (reading 'isRefractionEnabled')` in babylonjs-loaders (GLTF2 transmissionWeight getter)

I get this error when loading GLB with `SceneLoader.LoadAssetContainerAsync` (or when assigning material to a mesh):

```auto
TypeError: Cannot read properties of undefined (reading 'isRefractionEnabled')
  at e3.get (babylonjs-loaders.js:307:46)
  at babylonjs-loaders.js:4948:18

```

**Cause:** In the GLTF2 loader bundle, the getter for `transmissionWeight` (KHR\_materials\_transmission) reads:

`this._material.subSurface.isRefractionEnabled`

without checking if `_material` or `subSurface` exist. When the material is undefined or not PBR (e.g. StandardMaterial has no `subSurface`), `subSurface` is undefined and reading `.isRefractionEnabled` throws.

**Suggested fix:** Guard the read in the loader, e.g.:

- Getter: `this._material?.subSurface?.isRefractionEnabled ? this._material.subSurface.refractionIntensity : 0`
- Setter: only write when `this._material?.subSurface` exists.

I use **babylonjs 8.49.3** and **babylonjs-loaders 8.49.3**.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/7/3/7369ca4834b0093105bd3596155c553cfd0d23fb.png)

I can’t reproduce it on Playground, and create test-env for this case here: [https://test.game.1kit.net/](https://test.game.1kit.net/)

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [January 30, 2026, 8:05pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/8 "2026-01-30T20:05:53Z")

</div>

> [@onekit](#):
>
> `transmissionWeight`

It looks like it is because we create an adapter on a standardMaterial and not PBR. @MiiBond could you have a look ?

---

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 30, 2026, 8:18pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/9 "2026-01-30T20:18:50Z")

</div>

Hi @sebavan. You know, I’m not even sure it’s related to the BabylonJS code, because a couple of days ago, the textures on meshes I was working on suddenly turned black, and a lot of things stopped working because the global WebGL API was updated. And problems started pouring in from everywhere. I thought rolling back to previous versions would save me, but in the previous versions, I started getting errors about loading GLB files. And then I realized it’s not that simple and the solution could take time. And as luck would have it, this has become a blocker for my game development, and my eyes are already wet with tears.

---

<div class="post-metadata">

**Author:** ![MiiBond](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/miibond/32/4926_2.png) [@MiiBond](https://forum.babylonjs.com/u/MiiBond)\
**Post date:** [January 30, 2026, 8:44pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/10 "2026-01-30T20:44:01Z")

</div>

I’m not sure how the loading adapter could be created for a StandardMaterial. Do we know which GLB is triggering this issue? I can add guards in the loading adapter but it would be helpful to know the full story about why this is happening.

---

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 30, 2026, 8:51pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/11 "2026-01-30T20:51:41Z")

</div>

The issue is that the error occurs for all meshes, not just GLBs. It seems the engine tries to access `isRefractionEnabled` on the material before I even have a chance to assign it or before the material is fully initialized.  
My `Ground.ts` class:

```TS
import {
  Color3,
  Material,
  Mesh,
  MeshBuilder,
  PBRMaterial,
  PhysicsAggregate,
  PhysicsBody,
  PhysicsMotionType,
  PhysicsShapeBox,
  PhysicsShapeHeightField,
  PhysicsShapeType,
  Quaternion,
  Scene,
  StandardMaterial,
  Texture,
  Vector3,
} from 'babylonjs'
import ShapeMask from '@game/physics/ShapeMaskInterface'
import { GroundData } from '@game/map/LevelDataInterface'
import { PI, HALF_PI } from '@game/math/MathConstants'

export default class Ground {
  mesh: Mesh | null = null
  private fences: Mesh[] = []
  private fenceTexture: Texture | undefined
  private fenceMaterial: StandardMaterial | undefined
  private fenceMaterialOuter: StandardMaterial | undefined
  private grassBaseTexture: Texture | undefined
  private grassBaseMaterial: StandardMaterial | undefined

  constructor(public scene: Scene) {
    if (!scene) {
      throw new Error('Scene is not provided.')
    }
  }

  async create(data: GroundData, levelId: string): Promise<Mesh> {
    this.dispose()

    const { width, height, depth, uScale, vScale, subdivisions } = data
    const heightMap = data.heightMap ? '/levels/' + levelId + '/img/' + data.heightMap : undefined
    const fenceTextureImageFile = data.fenceTexture ? '/levels/' + levelId + '/img/' + data.fenceTexture : '/img/wooden-wall.jpg'
    const textureImageFile = data.texture ? '/levels/' + levelId + '/img/' + data.texture : '/ground/mossy.jpg'
    const pbrTextureBeginOfPath = data.pbrTexture ? '/levels/' + levelId + '/img/' + data.pbrTexture : undefined
    let mesh: Mesh
    let shape: PhysicsShapeBox | PhysicsShapeHeightField | undefined
    if (heightMap) {
      mesh = MeshBuilder.CreateGroundFromHeightMap(
        'ground',
        heightMap,
        {
          height: height,
          width: width,
          maxHeight: depth,
          subdivisions: subdivisions,
        },
        this.scene,
      )
      await new Promise<void>((resolve) => {
        mesh.onReady = () => resolve()
      })

      // console.log(heightMap)
      shape = await this.getShapeHeightMap(heightMap, width, height)
    } else {
      mesh = MeshBuilder.CreateBox('ground', { height: height, width: width, depth: depth }, this.scene)
      shape = this.getShapeBox(width, height, depth!)
    }

    // Material assignment: uncomment next line to use real textures; otherwise a default placeholder is used (Babylon requires mesh.material to exist)
    this.applyGroundMaterial(mesh, textureImageFile, uScale, vScale, pbrTextureBeginOfPath)
    if (!mesh.material) {
      this.applyDefaultGroundMaterial(mesh)
    }

    if (fenceTextureImageFile) {
      this.createFence(width, height, uScale, vScale, fenceTextureImageFile)
    }

    mesh.checkCollisions = true
    mesh.isPickable = true // for detect stand on surface
    mesh.metadata = { active: true, type: 'ground' }
    mesh.receiveShadows = true

    if (shape) {
      shape.filterMembershipMask = ShapeMask.Ground
      shape.filterCollideMask = ShapeMask.Item | ShapeMask.Wall | ShapeMask.Player

      if (heightMap) {
        // console.log(shape)
        const aggregate = new PhysicsAggregate(
          mesh,
          PhysicsShapeType.MESH,
          {
            mass: 0,
            friction: 1.2,
            restitution: 0.3,
          },
          this.scene,
        )
        aggregate.shape = shape
      } else {
        const body = new PhysicsBody(mesh, PhysicsMotionType.STATIC, false, this.scene)
        body.shape = shape
        shape.material = { friction: 3.5, restitution: 0.1 }
        body.setMassProperties({
          mass: 0,
        })
      }
    }

    this.mesh = mesh

    return mesh
  }

  /**
   * Applies ground material to the mesh (PBR or standard texture).
   * Enable/disable by calling this method from create() or commenting the call out.
   */
  private applyGroundMaterial(mesh: Mesh, textureImageFile: string, uScale: number, vScale: number, pbrTextureBeginOfPath?: string): void {
    if (!textureImageFile) return
    const material = pbrTextureBeginOfPath
      ? this.getPBRMaterial(pbrTextureBeginOfPath, uScale, vScale)
      : this.getMaterial(textureImageFile, uScale, vScale)
    this.setMeshMaterialWithoutNotifying(mesh, material)
  }

  /**
   * Applies a minimal default material so that mesh.material is never undefined.
   * Babylon (e.g. loaders) expects every mesh to have a material with properties like isRefractionEnabled.
   * Uses internal assign to avoid triggering onMaterialChangedObservable, which would run the loader's
   * observer and cause it to read isRefractionEnabled from undefined (old material) and throw.
   */
  private applyDefaultGroundMaterial(mesh: Mesh): void {
    this.scene.getMaterialById('groundMaterialPlaceholder')?.dispose()
    const material = new StandardMaterial('groundMaterialPlaceholder', this.scene)
    material.diffuseColor = new Color3(0.5, 0.5, 0.5)
    material.specularColor = new Color3(0, 0, 0)
    this.setMeshMaterialWithoutNotifying(mesh, material)
  }

  /**
   * Sets mesh material without triggering onMaterialChangedObservable.
   * Avoids babylonjs-loaders observer which reads material.isRefractionEnabled and throws when the
   * observer runs during the setter (old material can be undefined).
   */
  private setMeshMaterialWithoutNotifying(mesh: Mesh, material: Material): void {
    const data = (mesh as any)._internalAbstractMeshDataInfo as { _material: Material | null } | undefined
    if (!data) return
    const oldMat = data._material
    if (oldMat && (oldMat as any).meshMap) (oldMat as any).meshMap[mesh.uniqueId] = undefined
    data._material = material
    if (material && (material as any).meshMap) (material as any).meshMap[mesh.uniqueId] = mesh
  }

  private getShapeBox(width: number, height: number, depth: number) {
    return new PhysicsShapeBox(new Vector3(0, -height / 2, 0), Quaternion.Identity(), new Vector3(width, depth, height), this.scene)
  }

  private async getShapeHeightMap(heightMap: string, width: number, height: number): Promise<PhysicsShapeHeightField | undefined> {
    if (!this.scene) {
      throw new Error('Scene is not provided.')
    }

    const image = new Image()
    image.src = heightMap

    await new Promise<void>((resolve, reject) => {
      image.onload = () => resolve()
      image.onerror = reject
    })

    const canvas = document.createElement('canvas')
    canvas.width = image.width
    canvas.height = image.height

    const ctx = canvas.getContext('2d')
    if (!ctx) {
      throw new Error('Canvas Rendering Context 2D is not loaded.')
    }
    ctx.drawImage(image, 0, 0)

    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
    const heights: number[] = []

    for (let i = 0; i < imgData.height; i++) {
      for (let j = 0; j < imgData.width; j++) {
        const index = (i * imgData.width + j) * 4
        const heightValue = imgData.data[index] / 255
        heights.push(heightValue)
      }
    }
    const heightFieldData = new Float32Array(heights)
    // console.log('float32array', heightFieldData)
    return new PhysicsShapeHeightField(width, height, imgData.width, imgData.height, heightFieldData, this.scene)
  }

  private getPBRMaterial(pbrTextureBeginOfPath: string, uScale: number, vScale: number) {
    const albedo = pbrTextureBeginOfPath + '-albedo.png'
    const ao = pbrTextureBeginOfPath + '-ao.png'
    const height = pbrTextureBeginOfPath + '-height.png'
    const normal = pbrTextureBeginOfPath + '-normal-ogl.png'
    const metallic = pbrTextureBeginOfPath + '-metal.png'

    const albedoTexture = new Texture(albedo, this.scene)
    const aoTexture = new Texture(ao, this.scene)
    const heightTexture = new Texture(height, this.scene)
    const normalTexture = new Texture(normal, this.scene)
    const metallicRoughnessTexture = new Texture(metallic, this.scene)

    albedoTexture.uScale = uScale
    albedoTexture.vScale = vScale
    aoTexture.uScale = uScale
    aoTexture.vScale = vScale
    heightTexture.uScale = uScale
    heightTexture.vScale = vScale
    normalTexture.uScale = uScale
    normalTexture.vScale = vScale
    metallicRoughnessTexture.uScale = uScale
    metallicRoughnessTexture.vScale = vScale

    this.scene.getMaterialById('groundMaterial')?.dispose()
    const material = new PBRMaterial('groundMaterial', this.scene)

    material.albedoTexture = albedoTexture
    material.ambientTexture = aoTexture
    material.bumpTexture = normalTexture
    material.metallicTexture = metallicRoughnessTexture

    material.metallic = 1
    material.roughness = 1

    return material
  }

  private getMaterial(textureImageFile: string, uScale: number, vScale: number) {
    const grassBaseTexture = new Texture(textureImageFile, this.scene)
    grassBaseTexture.wrapU = Texture.WRAP_ADDRESSMODE
    grassBaseTexture.wrapV = Texture.WRAP_ADDRESSMODE
    grassBaseTexture.uScale = uScale
    grassBaseTexture.vScale = vScale

    this.scene.getMaterialById('groundMaterial')?.dispose()
    const material = new StandardMaterial('groundMaterial', this.scene)
    material.diffuseTexture = grassBaseTexture
    material.specularColor = new Color3(0, 0, 0)
    material.ambientColor = new Color3(0.01, 0.01, 0.01)
    material.diffuseColor = new Color3(0.8, 0.85, 0.8)
    material.maxSimultaneousLights = 10

    this.grassBaseTexture = grassBaseTexture
    this.grassBaseMaterial = material

    return material
  }

  private createFence(width: number, height: number, uScale: number, vScale: number, fenceTextureImageFile: string) {
    const fenceTexture = new Texture(fenceTextureImageFile, this.scene)
    fenceTexture.uScale = 1
    fenceTexture.vScale = 1

    // Inner material (opaque) - visible from inside the level
    this.scene.getMaterialById('fenceMaterial')?.dispose()
    const fenceMaterial = new StandardMaterial('fenceMaterial', this.scene)
    fenceMaterial.diffuseTexture = fenceTexture
    fenceMaterial.roughness = 1
    fenceMaterial.specularColor = new Color3(0, 0, 0)
    fenceMaterial.specularPower = 64
    fenceMaterial.backFaceCulling = true // Single-sided, visible only from inside
    fenceMaterial.alpha = 1.0

    // Outer material (semi-transparent) - visible from outside the level
    this.scene.getMaterialById('fenceMaterialOuter')?.dispose()
    const fenceMaterialOuter = new StandardMaterial('fenceMaterialOuter', this.scene)
    fenceMaterialOuter.diffuseTexture = fenceTexture
    fenceMaterialOuter.roughness = 1
    fenceMaterialOuter.specularColor = new Color3(0, 0, 0)
    fenceMaterialOuter.specularPower = 64
    fenceMaterialOuter.backFaceCulling = true // Single-sided, visible only from outside
    fenceMaterialOuter.alpha = 0.5
    fenceMaterialOuter.transparencyMode = Material.MATERIAL_ALPHABLEND

    const wallHeight = 8
    const planeThickness = 0.2 // Distance between inner and outer planes to prevent z-fighting

    // Front wall - inner plane (facing inside, z = height/2)
    const frontPlaneInner = MeshBuilder.CreateTiledPlane(
      'frontPlaneInner',
      { width, height: wallHeight, tileHeight: vScale, tileWidth: uScale },
      this.scene,
    )
    frontPlaneInner.metadata = { active: true, type: 'fence' }
    frontPlaneInner.material = fenceMaterial
    frontPlaneInner.position = new Vector3(0, wallHeight / 2, height / 2 - planeThickness)
    frontPlaneInner.checkCollisions = true

    // Front wall - outer plane (facing outside, z = height/2)
    const frontPlaneOuter = MeshBuilder.CreateTiledPlane(
      'frontPlaneOuter',
      { width, height: wallHeight, tileHeight: vScale, tileWidth: uScale },
      this.scene,
    )
    frontPlaneOuter.metadata = { active: true, type: 'fence' }
    frontPlaneOuter.material = fenceMaterialOuter
    frontPlaneOuter.position = new Vector3(0, wallHeight / 2, height / 2 + planeThickness)
    frontPlaneOuter.rotation.x = PI

    // Physics body for the front wall (using inner plane)
    const frontBody = new PhysicsBody(frontPlaneInner, PhysicsMotionType.STATIC, false, this.scene)
    frontBody.shape = new PhysicsShapeBox(new Vector3(0, 0, 0), Quaternion.Identity(), new Vector3(width, wallHeight, 0.5), this.scene)
    frontBody.setMassProperties({ mass: 0 })

    // Back wall - inner plane (facing inside, z = -height/2)
    const backPlaneInner = MeshBuilder.CreateTiledPlane(
      'backPlaneInner',
      { width, height: wallHeight, tileHeight: vScale, tileWidth: uScale },
      this.scene,
    )
    backPlaneInner.material = fenceMaterial
    backPlaneInner.metadata = { active: true, type: 'fence' }
    backPlaneInner.position = new Vector3(0, wallHeight / 2, -height / 2 + planeThickness)
    backPlaneInner.rotation.x = -PI
    backPlaneInner.checkCollisions = true

    // Back wall - outer plane (facing outside, z = -height/2)
    const backPlaneOuter = MeshBuilder.CreateTiledPlane(
      'backPlaneOuter',
      { width, height: wallHeight, tileHeight: vScale, tileWidth: uScale },
      this.scene,
    )
    backPlaneOuter.material = fenceMaterialOuter
    backPlaneOuter.metadata = { active: true, type: 'fence' }
    backPlaneOuter.position = new Vector3(0, wallHeight / 2, -height / 2 - planeThickness)

    // Physics body for the back wall (using inner plane)
    const backBody = new PhysicsBody(backPlaneInner, PhysicsMotionType.STATIC, false, this.scene)
    backBody.shape = new PhysicsShapeBox(new Vector3(0, 0, 0), Quaternion.Identity(), new Vector3(width, wallHeight, 0.5), this.scene)
    backBody.setMassProperties({ mass: 0 })

    // Left wall - inner plane (facing inside, x = width/2)
    const leftPlaneInner = MeshBuilder.CreateTiledPlane(
      'leftPlaneInner',
      { width: width, height: wallHeight, tileHeight: vScale, tileWidth: uScale, sideOrientation: 0 },
      this.scene,
    )
    leftPlaneInner.material = fenceMaterial
    leftPlaneInner.metadata = { active: true, type: 'fence' }
    leftPlaneInner.position = new Vector3(width / 2 - planeThickness, wallHeight / 2, 0)
    leftPlaneInner.checkCollisions = true
    leftPlaneInner.rotation.y = HALF_PI

    // Left wall - outer plane (facing outside, x = width/2)
    const leftPlaneOuter = MeshBuilder.CreateTiledPlane(
      'leftPlaneOuter',
      { width: width, height: wallHeight, tileHeight: vScale, tileWidth: uScale, sideOrientation: 0 },
      this.scene,
    )
    leftPlaneOuter.material = fenceMaterialOuter
    leftPlaneOuter.metadata = { active: true, type: 'fence' }
    leftPlaneOuter.position = new Vector3(width / 2 + planeThickness, wallHeight / 2, 0)
    leftPlaneOuter.rotation.y = -HALF_PI

    // Physics body for the left wall (using inner plane)
    const leftBody = new PhysicsBody(leftPlaneInner, PhysicsMotionType.STATIC, false, this.scene)
    const leftRotationQuaternion = Quaternion.FromEulerAngles(0, HALF_PI, 0)
    leftBody.shape = new PhysicsShapeBox(new Vector3(0, 0, 0), leftRotationQuaternion, new Vector3(0.5, wallHeight, width), this.scene)
    leftBody.setMassProperties({ mass: 0 })

    // Right wall - inner plane (facing inside, x = -width/2)
    const rightPlaneInner = MeshBuilder.CreateTiledPlane(
      'rightPlaneInner',
      { width: width, height: wallHeight, tileHeight: vScale, tileWidth: uScale, sideOrientation: 0 },
      this.scene,
    )
    rightPlaneInner.material = fenceMaterial
    rightPlaneInner.metadata = { active: true, type: 'fence' }
    rightPlaneInner.position = new Vector3(-width / 2 + planeThickness, wallHeight / 2, 0)
    rightPlaneInner.checkCollisions = true
    rightPlaneInner.rotation.y = -HALF_PI

    // Right wall - outer plane (facing outside, x = -width/2)
    const rightPlaneOuter = MeshBuilder.CreateTiledPlane(
      'rightPlaneOuter',
      { width: width, height: wallHeight, tileHeight: vScale, tileWidth: uScale, sideOrientation: 0 },
      this.scene,
    )
    rightPlaneOuter.material = fenceMaterialOuter
    rightPlaneOuter.metadata = { active: true, type: 'fence' }
    rightPlaneOuter.position = new Vector3(-width / 2 - planeThickness, wallHeight / 2, 0)
    rightPlaneOuter.rotation.y = HALF_PI

    // Physics body for the right wall (using inner plane)
    const rightBody = new PhysicsBody(rightPlaneInner, PhysicsMotionType.STATIC, false, this.scene)
    const rightRotationQuaternion = Quaternion.FromEulerAngles(0, -HALF_PI, 0)
    rightBody.shape = new PhysicsShapeBox(new Vector3(0, 0, 0), rightRotationQuaternion, new Vector3(0.5, wallHeight, width), this.scene)
    rightBody.setMassProperties({ mass: 0 })

    this.fenceTexture = fenceTexture
    this.fenceMaterial = fenceMaterial
    this.fenceMaterialOuter = fenceMaterialOuter

    // Store all fence planes for proper disposal
    this.fences.push(
      frontPlaneInner,
      frontPlaneOuter,
      backPlaneInner,
      backPlaneOuter,
      leftPlaneInner,
      leftPlaneOuter,
      rightPlaneInner,
      rightPlaneOuter,
    )
  }

  dispose(): void {
    this.fenceTexture?.dispose()
    this.fenceMaterial?.dispose()
    this.fenceMaterialOuter?.dispose()
    this.grassBaseTexture?.dispose()
    this.grassBaseMaterial?.dispose()

    if (this.mesh) {
      if (this.mesh.material) {
        this.disposeMaterial(this.mesh.material)
      }
      this.mesh.dispose(false, true)
      this.mesh = null
    }

    this.fences.forEach((fence) => {
      if (fence.material) {
        this.disposeMaterial(fence.material)
      }
      fence.dispose(false, true)
    })
    this.fences = []
  }

  private disposeMaterial(material: Material): void {
    if (material instanceof PBRMaterial) {
      material.albedoTexture?.dispose()
      material.ambientTexture?.dispose()
      material.bumpTexture?.dispose()
      material.metallicTexture?.dispose()
    } else if (material instanceof StandardMaterial) {
      material.diffuseTexture?.dispose()
    }
    material.dispose()
  }
}

```

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [January 30, 2026, 9:12pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/12 "2026-01-30T21:12:24Z")

</div>

@MiiBond has a lead on smthg I guess PR will be coming soon-ish 🙂

---

<div class="post-metadata">

**Author:** ![MiiBond](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/miibond/32/4926_2.png) [@MiiBond](https://forum.babylonjs.com/u/MiiBond)\
**Post date:** [January 30, 2026, 9:34pm UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/13 "2026-01-30T21:34:38Z")

</div>

PR is up.

> <https://github.com/BabylonJS/Babylon.js/pull/17785>
>
> Okay, this fixes a bug reported here:
> https://forum.babylonjs.com/t/regression-…in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/11
> 
> The issue is that the TransparencyHelper, created from within the \`KHR\_materials\_transmission\` extension can be called for any material type but the TransparencyHelper tries to use the loader's material adapter to check for transmission props. A material adapter is then created for the material, even if the material type doesn't match. This, of course, leads to problems.
> 
> Currently, the material adapter supports only \`PBRMaterial\` and \`OpenPBRMaterial\` but the bigger issue is that it only supports \*\*one\*\* of them at a time. If you load a glTF with OpenPBR support and then create a PBRMaterial later, the TransparencyHelper will try to use the OpenPBR material loading adapter...
> 
> This PR just checks if the incoming material is the same type as the one loaded with the glTF loader. If it's not, it ignores it.

---

<div class="post-metadata">

**Author:** ![onekit](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/onekit/32/49527_2.png) [@onekit](https://forum.babylonjs.com/u/onekit)\
**Post date:** [January 31, 2026, 12:15am UTC](https://forum.babylonjs.com/t/regression-in-8-47-2-typeerror-cannot-read-properties-of-undefined-reading-isrefractionenabled-in-babylonjs-loaders/62253/14 "2026-01-31T00:15:13Z")

</div>

You’re my hero! It works!!!
