Matter: external accessories ignore plugin-supplied manufacturer and model (BasicInformation always reports 'Homebridge')
Describe the bug
For external Matter accessories, accessory.manufacturer and accessory.model are collected, passed into the dedicated MatterServer, validated, sanitized and returned by the config layer — and then never read. The node's BasicInformation cluster gets a hardcoded vendorName: 'Homebridge' and a productName derived from displayName.
The effect a user sees in Apple Home, on the accessory details page of a plugin-provided external Matter accessory:
| Row | Shows | Should show |
|---|---|---|
| Manufacturer | Homebridge |
accessory.manufacturer |
| Model | the accessory's name | accessory.model |
Bridged Matter accessories are correct — AccessoryManager.createEndpointOptions() maps both fields onto bridgedDeviceBasicInformation. Only the external/standalone server path drops them.
The path, in v2.4.0
src/matter/ExternalMatterAccessoryPublisher.ts:100-101passes them in:manufacturer: accessory.manufacturer, model: accessory.model,src/matter/server/ServerConfig.ts:64-73validates and truncates both, and:106-107returns them in the resolved config:let manufacturer = config.manufacturer if (manufacturer !== undefined) { manufacturer = truncateString(manufacturer, 32, 'Manufacturer name').value }src/matter/server/ServerLifecycle.ts:319-326buildsbasicInformationwithout reading either one:nodeLabel: displayName.slice(0, 32), vendorId: VendorId(deps.commissioningManager.vendorId), vendorName: DEFAULT_BRIDGE_DEFAULTS.vendorName, // <- always 'Homebridge' productId: deps.commissioningManager.productId, productName: displayName.slice(0, 32), // <- name, not model productLabel: (stripVendorFromLabel(displayName, DEFAULT_BRIDGE_DEFAULTS.vendorName) || 'Bridge').slice(0, 64),
config.manufacturer and config.model have no other reader anywhere under src/matter/. The truncation limits in ServerConfig (32 chars for each) are exactly the BasicInformation constraints for VendorName/ProductName, so the intent to use them there seems clear — the wiring is just missing.
Suggested fix
vendorName: deps.config.manufacturer || DEFAULT_BRIDGE_DEFAULTS.vendorName,
productName: (deps.config.model || displayName).slice(0, 32),
productLabel: (stripVendorFromLabel(displayName, deps.config.manufacturer || DEFAULT_BRIDGE_DEFAULTS.vendorName) || deps.config.model || 'Device').slice(0, 64),
Note this mirrors the bridged path, which already falls back to accessory.model for productLabel when stripping the vendor consumes the whole name.
Two things worth deciding rather than assuming:
vendorIdstays as-is. It has to: an uncertified plugin cannot claim a real Matter vendor ID, andvendorNameis a free-text string with no relationship to it. Changing only the name is spec-legal.- Changing
BasicInformationon an already-commissioned node is an attribute write, not a structural change, so it should not need re-commissioning — but a controller that cached the old strings may keep showing them until it re-reads. Worth a line in the release notes either way.
To Reproduce
- A platform plugin that registers a Matter accessory as external, setting
accessory.manufacturerandaccessory.model. - Pair it with Apple Home.
- Open the accessory's settings → the Manufacturer row reads
Homebridgeand the Model row reads the accessory's name.
Reproduced on two unrelated households running homebridge-roborock-matter, which sets accessory.manufacturer = 'Roborock' on every robot; both show Homebridge. Log line confirming the external path:
[Matter/External] ✓ External Matter accessory published: <name> on port 5534 (bridge XX:XX:XX:XX:XX:XX)
Expected behavior
An external Matter accessory reports the manufacturer and model its plugin supplied, the same way a bridged one already does.
Homebridge Version
v2.4.0
Node.js Version
v24.19.0
Operating System
Ubuntu 26.04 LTS (also observed on a separate installation)
Source: homebridge/homebridge