Analysis
Ciao v1.3.7 crashes with an unhandled rejection during startup on Linux systems. The regression correlates with the switch from ip neigh show to ip -o link show in NetworkManager.getLinuxNetworkInterfaces() (commit f53c664f). The crash produces unhandled rejection dumps with no message or stack trace, suggesting an error is being swallowed or propagated uncaught somewhere in the startup promise chain.
Expected Behavior
Ciao should start without crashing on Linux. Network interface discovery should complete successfully, interfaces should be bound, and the mDNS responder should begin advertising services. The Node.js process should remain stable.
Steps To Reproduce
Steps to Reproduce
- Install
@homebridge/ciao@1.3.7 on a Linux system (e.g., Raspberry Pi OS, Debian)
- Create a basic service advertisement script:
const ciao = require('@homebridge/ciao');
const responder = ciao.getResponder();
const service = responder.createService({
name: 'Test',
type: 'test',
protocol: 'TCP',
port: 12345
});
service.advertise();
- Run the script with Node.js v22:
node test.js
- Observe that the process exits with an unhandled rejection almost immediately
- Alternatively, run under a process manager with auto-restart (e.g., systemd with
Restart=always) and observe a crash loop every ~45-50 seconds
Notes:
- Same script with
@homebridge/ciao@1.3.6 starts successfully
- Crash correlates with systems where
ip -o link show output contains interface lines with fewer than 3 space-separated parts, or where interface names contain spaces
Logs
## Logs / Crash Dumps
The crash manifests as an **unhandled rejection** with no message or stack trace. Node.js stability dumps are empty:
{
"version": 1,
"generatedAt": "2026-04-25T23:41:08.418Z",
"reason": "unhandled_rejection",
"process": {
"pid": 532641,
"platform": "linux",
"arch": "arm64",
"node": "22.22.2",
"uptimeMs": 45337
},
"host": {
"hostname": "<redacted>"
},
"snapshot": {
"generatedAt": "2026-04-25T23:41:08.419Z",
"capacity": 1000,
"count": 0,
"dropped": 0,
"events": [],
"summary": {
"byType": {}
}
}
}
**Pattern:** ~20 crashes over 16 minutes, ~48 seconds apart. Matches systemd `Restart=always` + `RestartSec=5`.
**Journal excerpt (filtered):**
Apr 26 21:04:50 node[1022784]: 2026-04-26T21:04:50.925-04:00 [ws] ⇄ res ✓ channels.status 202ms
No ciao-specific logs present; console output may be suppressed by OpenClaw's noise filter.
---
## Critique of the `ip -o link show` Parser (v1.3.7)
The v1.3.7 change from `ip neigh show` to `ip -o link show` introduced a new parsing path. While bounds checking exists, the parser makes assumptions about output format that may not hold across all Linux configurations.
### Example `ip -o link show` output:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000\ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000\ link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
### Parsing logic (v1.3.7):
const parts = lines[i].trim().split(NetworkManager.SPACE_PATTERN);
if (parts.length < 3 || !parts[1] || !parts[2]) {
continue;
}
const interfaceName = parts[1].replace(/:$/, "");
if (parts[2].includes("LOOPBACK")) {
continue;
}
### Potential edge cases:
- **Interface names with spaces**: `ip -o` wraps them in braces or escapes them differently than `ip neigh show`
- **Virtual interfaces**: Docker bridges, WireGuard, Tailscale interfaces may have unusual formatting
- **Lines with fewer parts**: Some kernel-generated lines or virtual interfaces may produce `parts.length < 3`
- **The `\ ` continuation**: `ip -o link show` uses `\` followed by spaces/tabs to indicate line continuation. The `os.EOL` split may not handle this correctly if the continuation creates embedded newlines
The v1.3.6 `ip neigh show` approach used `parts[5]` for interface names (`dev <iface>`), which was more reliable because the `dev` keyword provided a stable anchor regardless of line length.
Configuration
There's no ciao-level config file to edit.
Environment
Package: @homebridge/ciao | Version: 1.3.7 (regression from 1.3.6) | Platform: Linux (arm64, Debian-based) | Node.js: v22.22.2
Process Supervisor
systemd
Additional Context
Process Supervisior
This was discovered in an OpenClaw plugin context.
Expected Behavior
Gracefully skip malformed/short lines or handle missing parts[2] without crashing.
Actual Behavior
Unhandled rejection during startup with empty message/stack. Process crashes immediately, triggering systemd restart loop (~48s cycle).
Suggested Fix
Remove it entirely and say "Root cause unclear; needs investigation"
Analysis
Ciao v1.3.7 crashes with an unhandled rejection during startup on Linux systems. The regression correlates with the switch from
ip neigh showtoip -o link show in NetworkManager.getLinuxNetworkInterfaces()(commitf53c664f). The crash produces unhandled rejection dumps with no message or stack trace, suggesting an error is being swallowed or propagated uncaught somewhere in the startup promise chain.Expected Behavior
Ciao should start without crashing on Linux. Network interface discovery should complete successfully, interfaces should be bound, and the mDNS responder should begin advertising services. The Node.js process should remain stable.
Steps To Reproduce
Steps to Reproduce
@homebridge/ciao@1.3.7on a Linux system (e.g., Raspberry Pi OS, Debian)node test.jsRestart=always) and observe a crash loop every ~45-50 secondsNotes:
@homebridge/ciao@1.3.6starts successfullyip -o link showoutput contains interface lines with fewer than 3 space-separated parts, or where interface names contain spacesLogs
Configuration
There's no ciao-level config file to edit.Environment
Process Supervisor
systemd
Additional Context
Process Supervisior
This was discovered in an OpenClaw plugin context.
Expected Behavior
Gracefully skip malformed/short lines or handle missing
parts[2]without crashing.Actual Behavior
Unhandled rejection during startup with empty message/stack. Process crashes immediately, triggering systemd restart loop (~48s cycle).
Suggested Fix
Remove it entirely and say "Root cause unclear; needs investigation"