Skip to content

fix(gateway): include port in lock file payload [AI-assisted]#43752

Closed
liangmoyuTTC wants to merge 2 commits into
openclaw:mainfrom
LiaoyuanNing:fix/gateway-lock-include-port
Closed

fix(gateway): include port in lock file payload [AI-assisted]#43752
liangmoyuTTC wants to merge 2 commits into
openclaw:mainfrom
LiaoyuanNing:fix/gateway-lock-include-port

Conversation

@liangmoyuTTC

Copy link
Copy Markdown

Summary

  • Problem: When starting a gateway with --port <port>, the port override is a CLI argument only and is not persisted to the config file. External tools that scan lock files to discover running gateways cannot determine the actual listening port — they fall back to the config file default (18789), producing incorrect results when multiple gateways run on different ports via --profile.
  • Why it matters: Any tool that discovers gateways by reading lock files (e.g. ClawOS connect script) will report the wrong port for gateways started with --port, making auto-connection fail.
  • What changed: Added an optional port field to LockPayload. When acquireGatewayLock is called with a port option (already passed by runGatewayLoop), the actual listening port is now written into the lock file. readLockPayload also reads the field back.
  • What did NOT change (scope boundary): Lock acquisition logic, stale-lock detection, port-probe behavior, and config file handling are untouched. The field is optional so existing lock files without port remain valid.
  • AI disclosure: [AI-assisted] — fully tested, code reviewed and understood by contributor

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

None — no existing issue tracks this.

User-visible / Behavior Changes

Lock files at $TMPDIR/openclaw-$UID/gateway.<hash>.lock now include a port field when the gateway is started with an explicit port. No user-facing config or CLI changes.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS 24.1.0
  • Runtime/container: Node 22+

Steps

  1. Start default gateway: openclaw gateway --allow-unconfigured
  2. Start work gateway: openclaw --profile work gateway --allow-unconfigured --port 18790
  3. Read lock files: cat $TMPDIR/openclaw-$(id -u)/gateway.*.lock

Expected

  • Default lock file: {"pid":...,"port":18789,...}
  • Work lock file: {"pid":...,"port":18790,...}

Actual (before fix)

  • Both lock files have no port field. External tools default to 18789 for both.

Evidence

  • Failing test/log before + passing after
  • 2 new tests added: writes port to lock file when provided and omits port from lock file when not provided
  • Full test suite: 899 files, 7396 tests passed

Human Verification (required)

  • Verified scenarios: multi-profile gateways with different --port values, lock file content inspection
  • Edge cases checked: no port provided (field omitted), port provided (field written), existing lock files without port (backward compatible)
  • What you did not verify: Windows/Linux lock behavior (tested on macOS only)

Compatibility / Migration

  • Backward compatible? Yes — port is optional; old lock files without it are read correctly
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert the single commit
  • Files/config to restore: src/infra/gateway-lock.ts
  • Known bad symptoms reviewers should watch for: lock file parse errors (unlikely — field is optional and guarded by type check)

Risks and Mitigations

None — additive optional field with full backward compatibility.

@greptile-apps

greptile-apps Bot commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a gap where gateways started with --port did not persist the actual listening port to their lock file, causing external tools (e.g. ClawOS connect script) to always fall back to the default port 18789 when discovering running gateways. The fix is minimal and additive: an optional port field is appended to LockPayload, written during lock acquisition, and read back in readLockPayload, with no changes to lock acquisition logic, stale-lock detection, or port-probe behavior.

  • The implementation correctly mirrors the existing startTime field pattern (type-guarded write and read).
  • Backward compatibility is maintained — the field is optional and readLockPayload handles its absence gracefully.
  • Two new tests cover both the presence and absence of the port field in the written lock file.
  • The stored payload.port from an existing lock is not currently consumed by resolveGatewayOwnerStatus (which continues to probe opts.port); this is intentionally out of scope.
  • Minor: the write guard uses Number.isFinite(port) but does not validate the port range (1–65535); a defensive bounds check would prevent out-of-range values from being persisted.

Confidence Score: 4/5

  • Safe to merge — additive optional field with full backward compatibility and targeted test coverage.
  • The change is minimal, purely additive, and backward-compatible. It follows established patterns in the file, includes two focused new tests, and the author has explicitly documented scope boundaries. The only minor concern is the absence of a port range check on write, which is a style issue rather than a correctness problem given upstream CLI validation.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/infra/gateway-lock.ts
Line: 211-213

Comment:
**Consider adding port range validation**

`Number.isFinite(port)` accepts `0`, negative values, and values above `65535`, all of which are not valid TCP ports. While the port value presumably comes from CLI validation upstream, adding a range check here would make this defensive guard more precise and prevent misleading values from ever being written to the lock file.

```suggestion
      if (typeof port === "number" && Number.isFinite(port) && port > 0 && port <= 65535) {
        payload.port = port;
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: fb06fac

Comment thread src/infra/gateway-lock.ts Outdated
@liangmoyuTTC

Copy link
Copy Markdown
Author

Addressed Greptile's suggestion — added port range validation (port > 0 && port <= 65535) to the lock file write guard in ff6a1eb.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Apr 27, 2026
@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: current main still lacks gateway lock port persistence, and this PR is dirty against main and misses the current schema-backed parser path. The newer open PR #73338 now tracks the same lock-port contract with the schema/readback pieces plus the active TUI consumer for #42461.

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Review details

Best possible solution:

Close this PR as superseded and concentrate maintainer review on #73338. If #73338 does not land, extract its gateway-lock schema, writer, verified active-port reader, focused tests, and contributor credit into a narrow replacement.

Do we have a high-confidence way to reproduce the issue?

Yes. The source-level reproduction is high confidence: current main forwards lockPort into acquireGatewayLock, but the writer does not serialize it and the schema-backed reader has no port field.

Is this the best way to solve the issue?

No for this PR as-is. The requested direction is correct, but the branch needs a current-main schema update and has been superseded by #73338, which carries the fuller contract and consumer coverage.

Security review:

Security review cleared: The PR diff is limited to gateway lock payload code and focused tests, with no CI, dependency, package script, secret handling, downloaded artifact, or command-execution changes.

What I checked:

  • Current main schema omits port: LockPayload and LockPayloadSchema on current main include pid, createdAt, configPath, and optional startTime, but no port field. (src/infra/gateway-lock.ts:18, 58a0b077c1c5)
  • Current reader is schema-backed: readLockPayload returns safeParseJsonWithSchema(LockPayloadSchema, raw), so the new lock payload field must be present in the schema to survive structured reads. (src/infra/gateway-lock.ts:229, 58a0b077c1c5)
  • Current writer receives but omits port: acquireGatewayLock stores opts.port, but the payload written to disk still only contains pid, createdAt, configPath, and optional startTime. (src/infra/gateway-lock.ts:262, 58a0b077c1c5)
  • Gateway loop already forwards lockPort: runGatewayLoop passes params.lockPort into initial lock acquisition and restart reacquisition, so the missing surface is lock payload persistence/schema alignment. (src/cli/gateway-cli/run-loop.ts:87, 58a0b077c1c5)
  • This PR is stale and dirty: GitHub API reports this PR as open, mergeable: false, mergeable_state: dirty, with head ff6a1ebbfae42287d0fee5edf2087ff81f7150aa based on older main 7d6d112656223bee0025457d64dbc6464ffc5566. (ff6a1ebbfae4)
  • Superseding PR tracks the corrected implementation: Open PR fix(tui): follow active gateway port #73338 adds port to both the lock payload type and LockPayloadSchema, writes the runtime port, exposes readActiveGatewayLockPort, and wires TUI default resolution to that verified active lock port. (src/infra/gateway-lock.ts:22, 7699175a0d23)

Likely related people:

  • steipete: Recent history for src/infra/gateway-lock.ts includes the temp-dir lock move, lock validation hardening, port-liveness stale-lock recovery, and the zod reader refactor that defines the current schema-backed contract. (role: recent maintainer and lock implementation owner; confidence: high; commits: d4f895d8f2a4, 3fff943ba1bb, e6383a2c13e5; files: src/infra/gateway-lock.ts, src/infra/gateway-lock.test.ts)
  • TonyDerek-dot: Recent merged work touched the same gateway lock and run-loop surfaces for PID recycling and startup progress behavior. (role: adjacent gateway lock contributor; confidence: medium; commits: 5f6e3499f321; files: src/infra/gateway-lock.ts, src/infra/gateway-lock.test.ts, src/cli/gateway-cli/run-loop.ts)
  • vincentkoc: Recent commits touched gateway restart/run-loop behavior and gateway-lock test harness maintenance near the affected validation surface. (role: recent adjacent maintainer; confidence: medium; commits: 1f41b8b44ba0, 7c629d3e8bc8; files: src/cli/gateway-cli/run-loop.ts, src/infra/gateway-lock.test.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 58a0b077c1c5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant