Skip to content

Commit 4cf2cc9

Browse files
committed
fix(readiness): distinguish fresh listener checks
Signed-off-by: Rebecca Sliter <sliterrm@gmail.com>
1 parent 4971870 commit 4cf2cc9

4 files changed

Lines changed: 35 additions & 5 deletions

File tree

docs/reference/troubleshooting.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,12 +1079,14 @@ Blocked by: ssh`.
10791079

10801080
Current NemoClaw detects this case and kills the orphaned SSH process automatically before retrying the port check.
10811081
If you see the error on an older release, identify the SSH process.
1082-
Stop it only after fresh listener output confirms that your user owns the process, its command line is the stale SSH port forward for local port `18789`, and it has no active terminal or file transfer:
1082+
Use fresh listener output to confirm that your user owns the process and that it still listens on local port `18789`:
10831083

10841084
```bash
10851085
sudo lsof -i :18789 -sTCP:LISTEN -P -n
10861086
```
10871087

1088+
Inspect the process separately with `ps -p <PID> -o user=,args=`.
1089+
Stop it only when the owner is your user, the command line is the stale SSH port forward for local port `18789`, and no active terminal or file-transfer session uses that process.
10881090
Repeat the listener check immediately before you signal only the PID from that fresh result.
10891091
Then re-run `$$nemoclaw onboard`.
10901092

@@ -2970,7 +2972,7 @@ Run `fix-coredns.sh` to point CoreDNS at the container gateway IP instead, then
29702972
### `k3s` cannot find a freshly built image
29712973

29722974
After building a new sandbox image, `k3s` inside the gateway container sometimes fails to pull it even though the image exists on the host.
2973-
Remove the gateway registration, then rerun setup.
2975+
Remove the gateway registration, then resume onboarding.
29742976
If a privileged host gateway remains, do not use a host-wide process match.
29752977
Verify its live owner, exact gateway name and port, command line, PID file, runtime marker, and loaded sandbox namespace immediately before you stop it.
29762978

src/lib/readiness/gateway-production.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ describe("managed gateway port readiness (#7411)", () => {
528528
expect(observed.portConflictDetail).toContain(
529529
`sudo lsof -i :${gatewayPort} -sTCP:LISTEN -P -n`,
530530
);
531+
expect(observed.portConflictDetail).toContain("matching PID from that fresh result");
531532
expect(observed.portConflictDetail).not.toContain(`sudo kill ${process.pid}`);
532533
expect(observed.portConflictDetail).not.toContain("occupied by unknown");
533534
} finally {
@@ -566,11 +567,34 @@ describe("managed gateway port readiness (#7411)", () => {
566567
expect(detail).toContain("openshell-gateway (PID 100), python3 (PID 200)");
567568
expect(detail).toContain("Confirm PID 200 is not another NemoClaw gateway");
568569
expect(detail).toContain("sudo lsof -i :8080 -sTCP:LISTEN -P -n");
569-
expect(detail).toContain("signal only a PID from that fresh result");
570+
expect(detail).toContain("signal only the matching PID from that fresh result");
570571
expect(detail).not.toContain("sudo kill 200");
571572
expect(detail).not.toContain("sudo kill 100");
572573
});
573574

575+
it("requires fresh proof for every unverified listener before stopping multiple processes (#9118)", () => {
576+
const processNames = new Map([
577+
[200, "python3"],
578+
[300, "node"],
579+
]);
580+
const owners = describeGatewayPortOwners(
581+
{ pids: [], unverifiedPids: [200, 300] },
582+
(pid) => processNames.get(pid) ?? null,
583+
);
584+
const detail = gatewayPortConflictDetail(
585+
8080,
586+
{ ok: false, process: "unknown", pid: null, reason: "port 8080 is in use (EADDRINUSE)" },
587+
"multiple-owners",
588+
owners,
589+
);
590+
591+
expect(detail).toContain("python3 (PID 200), node (PID 300)");
592+
expect(detail).toContain("Confirm PIDs 200, 300 are not another NemoClaw gateway");
593+
expect(detail).toContain("sudo lsof -i :8080 -sTCP:LISTEN -P -n");
594+
expect(detail).toContain("signal only the matching PIDs from that fresh result");
595+
expect(detail).not.toContain("sudo kill");
596+
});
597+
574598
it("recommends releasing a verified gateway environment without a process stop command (#9118)", () => {
575599
const owners = describeGatewayPortOwners(
576600
{ pids: [100], unverifiedPids: [] },

src/lib/readiness/gateway-production.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,14 @@ function gatewayPortConflictRemediation(
567567
}
568568
const subject =
569569
stopPids.length === 1 ? `PID ${stopPids[0]} is` : `PIDs ${stopPids.join(", ")} are`;
570+
const stopInstruction =
571+
stopPids.length === 1
572+
? "Stop that process through its service manager, or signal only the matching PID from that fresh result before retrying."
573+
: "Stop each matching process through its service manager, or signal only the matching PIDs from that fresh result before retrying.";
570574
return (
571575
`Confirm ${subject} not another NemoClaw gateway. ` +
572576
`Recheck the listener set immediately before stopping a process: sudo lsof -i :${gatewayPort} -sTCP:LISTEN -P -n. ` +
573-
"Stop it through its service manager, or signal only a PID from that fresh result before retrying."
577+
stopInstruction
574578
);
575579
}
576580

test/onboard-gateway-port-conflict-fast-fail.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe("onboard gateway port conflict readiness (#6752)", () => {
121121
expect(combined).toContain(
122122
`sudo lsof -i :${String(gatewayPort)} -sTCP:LISTEN -P -n`,
123123
);
124-
expect(combined).toContain("signal only a PID from that fresh result");
124+
expect(combined).toContain("signal only the matching PID from that fresh result");
125125
expect(combined).not.toMatch(/sudo kill \d+/);
126126
},
127127
);

0 commit comments

Comments
 (0)