feat(gateway): add integration test and changelog for mDNS fixes
- Add bonjour-errors.integration.test.ts with 8 tests - Update CHANGELOG.md with unreleased section documenting fixes - Fix MDNS → MDNSSERVER pattern in bonjour-ciao.ts Completes recommendations for #3821, #3815, #4501
This commit is contained in:
parent
85294f19f7
commit
2f70888a77
10
CHANGELOG.md
10
CHANGELOG.md
@ -2,6 +2,16 @@
|
||||
|
||||
Docs: https://docs.openclaw.ai
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixes
|
||||
- Gateway: fix crash resilience for mDNS/Bonjour errors during network interface changes (sleep/wake, WiFi reconnect). (#3821)
|
||||
- Added error patterns for "IPv4 address changed" and "illegal state" assertions from @homebridge/ciao.
|
||||
- Added `--no-bonjour` CLI flag to disable mDNS advertising entirely.
|
||||
- Gateway: improve handling of transient network errors to prevent crashes. (#3815, #4501)
|
||||
- Added ERR_ASSERTION to transient network error codes.
|
||||
- Better detection of mDNS-related assertion errors.
|
||||
|
||||
## 2026.1.29
|
||||
Status: stable.
|
||||
|
||||
|
||||
@ -21,7 +21,8 @@ export function ignoreCiaoCancellationRejection(reason: unknown): boolean {
|
||||
const isTransientError = BONJOUR_TRANSIENT_ERRORS.some((pattern) => message.includes(pattern));
|
||||
|
||||
// Also catch AssertionError from MDNServer (common during network changes)
|
||||
const isAssertionError = errorName === "ASSERTIONERROR" && message.includes("MDNS");
|
||||
// Note: The error message typically contains "MDNSServer" in the stack trace
|
||||
const isAssertionError = errorName === "ASSERTIONERROR" && message.includes("MDNSSERVER");
|
||||
|
||||
if (!isTransientError && !isAssertionError) {
|
||||
return false;
|
||||
|
||||
94
src/infra/bonjour-errors.integration.test.ts
Normal file
94
src/infra/bonjour-errors.integration.test.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
||||
import process from "node:process";
|
||||
|
||||
import {
|
||||
installUnhandledRejectionHandler,
|
||||
isTransientNetworkError,
|
||||
isAbortError,
|
||||
} from "./unhandled-rejections.js";
|
||||
import { ignoreCiaoCancellationRejection } from "./bonjour-ciao.js";
|
||||
import { registerUnhandledRejectionHandler } from "./unhandled-rejections.js";
|
||||
|
||||
describe("mDNS error handling integration", () => {
|
||||
let originalExit: typeof process.exit;
|
||||
|
||||
beforeAll(() => {
|
||||
originalExit = process.exit.bind(process);
|
||||
installUnhandledRejectionHandler();
|
||||
registerUnhandledRejectionHandler(ignoreCiaoCancellationRejection);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
process.exit = originalExit;
|
||||
});
|
||||
|
||||
describe("error detection functions", () => {
|
||||
it("detects IPv4 address change as transient network error", () => {
|
||||
const mdnsError = Object.assign(
|
||||
new Error("Reached illegal state! IPv4 address changed from undefined to defined!"),
|
||||
{
|
||||
name: "AssertionError",
|
||||
code: "ERR_ASSERTION",
|
||||
},
|
||||
);
|
||||
|
||||
expect(isTransientNetworkError(mdnsError)).toBe(true);
|
||||
});
|
||||
|
||||
it("detects MDNSServer illegal state as transient network error", () => {
|
||||
const mdnsError = new Error("MDNSServer: Reached illegal state during network update");
|
||||
|
||||
expect(isTransientNetworkError(mdnsError)).toBe(true);
|
||||
});
|
||||
|
||||
it("detects AbortError correctly", () => {
|
||||
const abortError = Object.assign(new Error("This operation was aborted"), {
|
||||
name: "AbortError",
|
||||
});
|
||||
|
||||
expect(isAbortError(abortError)).toBe(true);
|
||||
});
|
||||
|
||||
it("does not treat fatal errors as transient", () => {
|
||||
const fatalError = Object.assign(new Error("Out of memory"), {
|
||||
code: "ERR_OUT_OF_MEMORY",
|
||||
});
|
||||
|
||||
expect(isTransientNetworkError(fatalError)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ciao cancellation handler", () => {
|
||||
it("handles CIAO announcement cancelled error", () => {
|
||||
const ciaoError = new Error("CIAO announcement cancelled due to network change");
|
||||
|
||||
expect(ignoreCiaoCancellationRejection(ciaoError)).toBe(true);
|
||||
});
|
||||
|
||||
it("handles IPv4 address change error", () => {
|
||||
const mdnsError = Object.assign(
|
||||
new Error("Reached illegal state! IPv4 address changed from undefined to defined!"),
|
||||
{
|
||||
name: "AssertionError",
|
||||
code: "ERR_ASSERTION",
|
||||
},
|
||||
);
|
||||
|
||||
expect(ignoreCiaoCancellationRejection(mdnsError)).toBe(true);
|
||||
});
|
||||
|
||||
it("handles MDNSServer illegal state error", () => {
|
||||
const mdnsError = Object.assign(new Error("MDNSServer: Reached illegal state"), {
|
||||
name: "AssertionError",
|
||||
});
|
||||
|
||||
expect(ignoreCiaoCancellationRejection(mdnsError)).toBe(true);
|
||||
});
|
||||
|
||||
it("does not handle unrelated errors", () => {
|
||||
const genericError = new Error("Something went wrong");
|
||||
|
||||
expect(ignoreCiaoCancellationRejection(genericError)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user