homebridge/homebridge · error

Plugin '${this.getPluginIdentifier()}' tried to register an

Error message

Plugin '${this.getPluginIdentifier()}' tried to register an accessory '${name}' which has already been registered!

What it means

Plugin.registerAccessory() maintains a Map of accessory name -> constructor for the plugin. Calling api.registerAccessory() twice with the same accessory name is treated as a plugin bug (usually a double-initialization) and throws immediately instead of silently overwriting the first registration.

Source

Thrown at src/plugin.ts:109

    }

    this.loadContext = {
      engines: packageJSON.engines,
      dependencies: packageJSON.dependencies,
    }
  }

  public getPluginIdentifier(): PluginIdentifier { // return full plugin name with scope prefix
    return (this.scope ? `${this.scope}/` : '') + this.pluginName
  }

  public getPluginPath(): string {
    return this.pluginPath
  }

  public registerAccessory(name: AccessoryName, constructor: AccessoryPluginConstructor): void {
    if (this.registeredAccessories.has(name)) {
      throw new Error(`Plugin '${this.getPluginIdentifier()}' tried to register an accessory '${name}' which has already been registered!`)
    }

    if (!this.disabled) {
      log.info('Registering accessory \'%s\'', `${this.getPluginIdentifier()}.${name}`)
    }

    this.registeredAccessories.set(name, constructor)
  }

  public registerPlatform(name: PlatformName, constructor: PlatformPluginConstructor): void {
    if (this.registeredPlatforms.has(name)) {
      throw new Error(`Plugin '${this.getPluginIdentifier()}' tried to register a platform '${name}' which has already been registered!`)
    }

    if (!this.disabled) {
      log.info('Registering platform \'%s\'', `${this.getPluginIdentifier()}.${name}`)
    }

View on GitHub (pinned to edf5493034)

Solutions

  1. Search the plugin for duplicate api.registerAccessory() calls with the same name and remove/merge them.
  2. Guard registration with a module-level flag so the initializer only registers once.
  3. Ensure the plugin initializer is only invoked once per process (avoid re-requiring/re-executing the module).
  4. Check for duplicated name string literals — use a single exported constant for each accessory name.

Example fix

// before
export default (api) => {
  api.registerAccessory('MyLight', MyLight)
  api.registerAccessory('MyLight', MyLightAlt) // throws
}
// after
export default (api) => {
  api.registerAccessory('MyLight', MyLight)
}
Defensive patterns

Strategy: validation

Validate before calling

const registered = new Set()
function registerOnce(api, name, ctor) {
  if (registered.has(name)) return
  api.registerAccessory(name, ctor)
  registered.add(name)
}

Try / catch

try {
  api.registerAccessory('MyLight', MyLight)
} catch (e) {
  if (e instanceof Error && e.message.includes('already been registered')) {
    log.warn('Accessory already registered; ignoring duplicate registration')
  } else throw e
}

Prevention

When it happens

Trigger: A plugin's default export (initializer) calls api.registerAccessory('MyAccessory', ...) twice — e.g. the initializer runs twice, or the same name is registered conditionally in two branches that both execute.

Common situations: Hot-reload/dev setups that re-require the plugin module and re-run the initializer on the same API instance; copy-pasted registerAccessory calls with duplicate name strings; bundling issues where the plugin module is instantiated twice.

Related errors


AI-assisted analysis of homebridge/homebridge@edf5493034 (2026-08-30). Data as JSON: /api/errors/ae19c0631e298e9d. Report an issue: GitHub.