# Invalid Capability

**URL:** <https://community.homey.app/t/invalid-capability/116159>\
**Category:** Developers\
**Created:** [September 16, 2024, 4:18pm UTC](https://community.homey.app/t/invalid-capability/116159 "2024-09-16T16:18:57Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![makleso6](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/makleso6/32/78907_2.png) [@makleso6](https://community.homey.app/u/makleso6)\
**Post date:** [September 16, 2024, 4:18pm UTC](https://community.homey.app/t/invalid-capability/116159/1 "2024-09-16T16:18:57Z")

</div>

Hi! I develop app  
when setCapabilityOptions with empty object and read it app throw a error  
2024-09-16T16:00:00.401Z [err] [ManagerDrivers] [Driver:light] [Device:5b53fe8d-6b85-4d03-ab98-4ad17974cbff] Device.onInit Error: Error: Invalid Capability: dim

here is my code

```auto
if (!this.hasCapability(capability)) {
  await this.addCapability(capability);
   await this.setCapabilityOptions(capability, {});
}
const capabilityOptions = this.getCapabilityOptions(capability);

expect get empty object {} in capabilityOptions

```

---

<div class="post-metadata">

**Author:** ![robertklep](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/robertklep/32/160628_2.png) [@robertklep](https://community.homey.app/u/robertklep)\
**Post date:** [September 16, 2024, 4:50pm UTC](https://community.homey.app/t/invalid-capability/116159/2 "2024-09-16T16:50:25Z")

</div>

So on which call does it fail exactly?

---

<div class="post-metadata">

**Author:** ![makleso6](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/makleso6/32/78907_2.png) [@makleso6](https://community.homey.app/u/makleso6)\
**Post date:** [September 16, 2024, 7:40pm UTC](https://community.homey.app/t/invalid-capability/116159/3 "2024-09-16T19:40:23Z")

</div>

> [@makleso6](#):
>
> So on which call does it fail exactly?

`const capabilityOptions = this.getCapabilityOptions(capability);`

---

<div class="post-metadata">

**Author:** ![robertklep](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/robertklep/32/160628_2.png) [@robertklep](https://community.homey.app/u/robertklep)\
**Post date:** [September 17, 2024, 5:23am UTC](https://community.homey.app/t/invalid-capability/116159/4 "2024-09-17T05:23:07Z")

</div>

It could be that adding a new capability in `onInit` requires that method to end before you can use the capability, or retrieve its options.

So something like this:

```auto
async onInit() {
  if (!this.hasCapability(capability)) {
    await this.addCapability(capability);
    await this.setCapabilityOptions(capability, {});
  }
  setTimeout(() => this.onInit2(), 0);
}

async onInit2() {
  const capabilityOptions = this.getCapabilityOptions(capability);
}

```

---

<div class="post-metadata">

**Author:** ![David\_Piper](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/david_piper/32/120919_2.png) [@David\_Piper](https://community.homey.app/u/David_Piper)\
**Post date:** [September 27, 2025, 10:32am UTC](https://community.homey.app/t/invalid-capability/116159/6 "2025-09-27T10:32:19Z")

</div>

@makleso6 Hi Maxim - I suspect you have moved on from this problem; but for the sake of logging my own frustrations and (hopefully solutions), I shall post this here…

I too suffered with this problem. It appears that, as @robertklep suggested capabilities are not fully instantiated for the device until _onInit_ has completed. There is a second method [onAdded](https://apps-sdk-v3.developer.homey.app/Device.html#onAdded). When I place _getCapabilitiesOptions()_ in the _onAdded()_ method it works. Clearly there is a lifecycle that devices pass through. Our problem, as developers of Homey apps, is the sparsity (aka complete lack) of information around such important details as what the lifecycle is.

I will continue to experiment with _onAdded_ and report back here.

---

<div class="post-metadata">

**Author:** ![David\_Piper](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/david_piper/32/120919_2.png) [@David\_Piper](https://community.homey.app/u/David_Piper)\
**Post date:** [September 27, 2025, 11:08am UTC](https://community.homey.app/t/invalid-capability/116159/7 "2025-09-27T11:08:12Z")

</div>

## Device Lifecycle

Elaborating on what I have found so far… The (start of) the lifecycle for a device seems to be:

```javascript
Driver.onMapDeviceClass - device "quasi-exists" - you can specify which class is the concrete instantiation of the device
Device.onInit - the first time you can programmatically do stuff with the device
Device.onAdded - the device and its capabilities exist "fully"

```

The usage I am making of these methods is:

> **onMapDeviceClass**
>
> Assign the class that will be the code base for the device. Using this method the same driver can manage different classes of device, for example.
> 
> > **Summary**
> >
> > This text will be hidden

> **onInit**
>
> Add a distinct set of capabilities to each different class of device - in this method it is not possible to change the capability options which you will (probably) want to do. In my app implementation, the _capabilities_ entry in the driver manifest is an empty array - all capabilities are added programmatically.
> 
> > **Summary**
> >
> > This text will be hidden

> **onAdded**
>
> Set the options of the capabilities - most typically changing the titles so that sub-capabilities are distinguished from each other in the Homey UI

My device classes are arranged in an inheritance hierarchy.

1. homey.device is the base class (obviously)
2. krakenDevice is an abstract class that extends homey.device
3. productTariff is one of three concrete device classes that extend krakenDevice

By using onMapDeviceClass I ensure that each device is instantiated by the correct concrete device class. This arrangement seems to work very well.
