{"record":{"id":"aa78c8cad4cf43c9","repo":"homebridge/homebridge","slug":"pluginidentifier-platformname-attempt-to-u","errorCode":null,"errorMessage":"${pluginIdentifier} - ${platformName} attempt to unregister an accessory that isn't PlatformAccessory!","messagePattern":"(.+?) - (.+?) attempt to unregister an accessory that isn't PlatformAccessory!","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/api.ts","lineNumber":813,"sourceCode":"        throw new TypeError(`${pluginIdentifier} - ${platformName} attempt to register an accessory that isn't PlatformAccessory!`)\n      }\n\n      accessory._associatedPlugin = pluginIdentifier\n      accessory._associatedPlatform = platformName\n    })\n\n    this.emit(InternalAPIEvent.REGISTER_PLATFORM_ACCESSORIES, accessories)\n  }\n\n  updatePlatformAccessories(accessories: PlatformAccessory[]): void {\n    this.emit(InternalAPIEvent.UPDATE_PLATFORM_ACCESSORIES, accessories)\n  }\n\n  unregisterPlatformAccessories(pluginIdentifier: PluginIdentifier, platformName: PlatformName, accessories: PlatformAccessory[]): void {\n    accessories.forEach((accessory) => {\n      // noinspection SuspiciousTypeOfGuard\n      if (!(accessory instanceof PlatformAccessory)) {\n        throw new TypeError(`${pluginIdentifier} - ${platformName} attempt to unregister an accessory that isn't PlatformAccessory!`)\n      }\n    })\n\n    this.emit(InternalAPIEvent.UNREGISTER_PLATFORM_ACCESSORIES, accessories)\n  }\n\n  /**\n   * Check if Matter is available in this version of Homebridge\n   * @returns true if Homebridge version satisfies >= 2.0.0-alpha.0\n   */\n  isMatterAvailable(): boolean {\n    return semver.gte(this.serverVersion, '2.0.0-alpha.0')\n  }\n\n  /**\n   * Check if Matter is enabled for this bridge\n   * For main bridge: returns true if Matter is enabled in `bridge.matter` config\n   * For child bridge: returns true if Matter is enabled in the `_bridge.matter` config","sourceCodeStart":795,"sourceCodeEnd":831,"githubUrl":"https://github.com/homebridge/homebridge/blob/edf54930340d67cade23d01abd41b03cd9621e8b/src/api.ts#L795-L831","documentation":"unregisterPlatformAccessories() applies the same instanceof guard before emitting UNREGISTER_PLATFORM_ACCESSORIES, since removing a non-PlatformAccessory from the bridge would corrupt accessory state. Passing anything other than real PlatformAccessory instances throws a TypeError.","triggerScenarios":"Calling api.unregisterPlatformAccessories(pluginIdentifier, platformName, accessories) with plain objects, stale/foreign accessory copies, or items reconstructed from persisted JSON instead of the actual accessory objects returned by the `didRegisterPlatformAccessories` event or kept by the plugin.","commonSituations":"Dynamic platforms removing accessories after holding them in a custom cache that was serialized/deserialized; plugin reloads losing the original instances; duplicate hap-nodejs copies making instanceof fail.","solutions":["Keep references to the actual PlatformAccessory instances you registered and pass those to unregisterPlatformAccessories.","Recreate a real PlatformAccessory via `new PlatformAccessory(name, uuid)` if the original was lost, then unregister it.","Deduplicate @homebridge/hap-nodejs so instanceof checks match the host's class.","Verify the array does not contain undefined entries (e.g. from a failed lookup filter)."],"exampleFix":"// before\nthis.api.unregisterPlatformAccessories(pluginName, platformName, this.cache.map(a => JSON.parse(a)));\n// after\nconst toRemove = this.cache.map(a => this.accessories.get(a.uuid)!).filter(a => a instanceof PlatformAccessory);\nthis.api.unregisterPlatformAccessories(pluginName, platformName, toRemove);","handlingStrategy":"type-guard","validationCode":"const valid = accessories.filter(a => a instanceof PlatformAccessory);\nif (valid.length !== accessories.length) {\n  log.warn('Skipping non-PlatformAccessory items in unregister call');\n}","typeGuard":"function isPlatformAccessory(a: unknown): a is PlatformAccessory {\n  return a instanceof PlatformAccessory;\n}","tryCatchPattern":"try {\n  api.unregisterPlatformAccessories(plugin, platformName, accessories);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('unregister')) {\n    log.error('Only unregister accessories originally obtained from registration events');\n  }\n}","preventionTips":["Subscribe to `api.on('didRegisterPlatformAccessories')` and store those exact instances for later unregistration.","Never unregister accessories reconstructed from serialized state.","Filter arrays with an instanceof guard before calling unregister.","Deduplicate hap-nodejs copies so instanceof stays reliable."],"tags":["plugin-api","type-error","platform-accessory","unregistration"],"backgroundTag":"invalid-argument-type","analyzedSha":"edf54930340d67cade23d01abd41b03cd9621e8b","analyzedAt":"2026-08-30T21:28:53.235Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}