TypeError: Cannot set property version of [object Object] which only has a getter

I’m currently developing a space game called Annihilation using Babylon.js and recently decided to start working on updating to Babylon 5.0. I’m now getting and error with Babylon 5 (alpha 61) where I can’t set Engine.prototype.version without Babylon throwing a TypeError (title). Renaming the property works fine, though I would prefer to keep the current property name. How can I fix this?

The game has other libraries and dependencies that make creating a playground for it very difficult. Please use this link to access the game, and F12/Devtools to view the source code and such.

It seems to me it is a problem with typescript. Maybe updating typescript to a newer version has revealed a bug in your source?

Given the error, it seems you are setting a value to a property that has only a getter. So, something like:

private _version: number;

public get version() {
    return this._version;

myobj.version = 23;

As I didn’t define a setter, I will get the error you reported when doing myobj.version = 23;.

Huh… Its done using plain Javascript, and my version declaration is pretty much game.version = "...". I found that if I remove the property declaration, version returns undefined.

Ah yes, it’s true you will also have the same error in plain js (when using Object.defineProperty) if you define a getter and not a setter for a property!

But the problem is the same: you defined a getter for a property and no setter.

My declaration is roughly equivalent to this though:

Object.prototype.assign = function(obj){Object.assign(this,obj)};
let game = new Engine(...); 

I’m not using Object.defineProperty. The only thing I can think of is that I’ve done the shortcut but that should not change anything. Maybe something like Object.prototype.assign = function(obj){this = {...this,...obj}}; would copy all of Babylon correctly?

The thing is, why are you writing to the version property of the Babylon engine? You should only read from it.


I think there may be a collision with the version property you add that way and the existing version property in Babylon engine (which only has a getter).

1 Like

I haven’t checked for that as DevTools is blocked on my school Chromebook, but console.dir would probably reveal the issue. I’ll take a look at the Babylon source code and see if they added that. Thank you!

The error appears to be in Babylon’s source code:

Object.defineProperty(ThinEngine.prototype, "version", {
         * Returns the version of the engine
        get: function () {
            return this._webGLVersion;
        enumerable: false,
        configurable: true

Since Engine inherits from ThinEngine, this should be loaded into game.version - though its just returns undefined

Are you saying that engine.version returns undefined?

Just wondering - Why are you assigning new properties to the engine this way? and why are you assigning BABYLON onto window?

Also, upgrading babel can cause this. I think the change was about a year ago. Typescript 3.7 also had a change impacting setters and using object.define in the constructor. You can read about it here https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier

Engine.Version doesn’t return undefined - that works fine. Engine.prototype.version returns undefined, and that is what I’m changing.

As for assigning BABYLON to window: It’s simply a matter of convenience. taking away all the BABYLONs in the code makes things more readable.

Finally, for assigning new properties to the engine. I’m simply using the engine object to store game metadata (e.g. the version, states of enabled features, etc.) since its creates less variables.

I think just renaming your property to gameVersion would resolve the error, but I think it would be helpful to create a separate Game class that has properties engine and version and store any other game data there as well.


I’m probably just gonna do game.engine as the engine instead of game. It would be great if the Babylon devs could fix this though since Engine.prototype.version/game.version returns undefined so it’s kind of useless.

That’s not a bug, so there is nothing to fix.

This is a getter, a completely valid js definition. Assign is nice, but doesn’t work as you expect when it comes to property definitions.


Why is there a getter/property defined at all if it isn’t used and just returns undefined? Just curious.

In this playground engine.version is 2 for me (for WebGL2). I’m guessing your invalid assign statement results in it being undefined thou.
Edit: oops I assumed you were using engine.version like I did above, but if you’re using Engine.prototype.version to try to get the version then that’s the wrong approach as answered below. :point_down: :slightly_smiling_face:

You are mixing scope and prototype I guess.

version is defined as a property in TS (getter only) on the ThinEngine class.

Once transpiled it ends up being the defineProperty code you showed above.

The issue is then scoping: calling prototype.version is excecuting the version code on the prototype scope where obviously the value is not defined whereas if you call it on an instance the scope being the instance one makes it all ok.



what @sebavan said :slight_smile:

Besides, you said it yourself:

You are not meant to copy the prototype of a class to another class, you are meant to instantiate it. using the new keyword js takes care of the assignments for you.

@RaananW /@sebavan
I’m not copying a property between classes. I instantiate it first then try to change the property of the newly created engine object - that’s it. The property in question is new BABYLON.Engine(...).version. I’ve refactored my code so I’m using the build property instead, so no worries.

Fwiw, the static get is working as expected per mdn. getter - JavaScript | MDN

class MyConstants {
  static get foo() {
    return 'foo';

console.log(MyConstants.foo); // 'foo'
MyConstants.foo = 'bar';
console.log(MyConstants.foo); // 'foo', a static getter's value cannot be changed