Skip to content

Client machine listener and standalone proxy share the same default loopback port, making management failures misdiagnosable #4972

Description

@lidge-jun

Client or integration

Other (the bundled ocx CLI of this project)

Area

Proxy and routing

Summary

The connected-client machine listener and the standalone proxy both default to the same loopback
port, and both answer /healthz with an opencodex identity. The CLI's liveness probe cannot
tell them apart, so on a client machine every management-backed ocx subcommand is addressed to
a listener that structurally serves no management route.

// src/client/machine-listener.ts:81-82
port: port ?? config.port ?? 10100,
hostname: "127.0.0.1",

That listener rejects every /api/* and /v1/* path (src/client/machine-listener.ts:51) and
answers the rejection with a 404 whose body is {"error":"not_found","method":…,"path":…}
(src/client/machine-listener.ts:38). The real management handler's unknown-id answer is
{"error":"not found"} (src/server/management/model-routes.ts:789). The two differ by one
character — an underscore against a space — which is not a difference an operator can be expected
to notice.

The collision is the root enabler rather than the parser gap on top of it. PR #4959 makes the CLI
read the role discriminator the client listener already publishes, which fixes the diagnosis;
it does not stop the two listeners from claiming the same port in the first place, and a shared
default is what puts an operator in front of the ambiguous 404 at all.

This was found while investigating #4662, where the reporter concluded that an unrelated relay on
port 10101 was occupying "the management port". That diagnosis was wrong in an instructive way:
there is no second management port anywhere in the tree, management rides the same listener, and
findLiveProxy had simply resolved the client listener. A collision that makes a whole class of
failures misdiagnosable is worth recording on its own, separately from the one misdiagnosis it
produced.

Reproduction

Static, from source at dev a0f611d4aceb9476d44268e43722273b7b211846:

  1. Run a connected-client machine listener with no explicit port. It binds 127.0.0.1:10100.
  2. findLiveProxy probes /healthz; isOpencodexHealthz (src/server/proxy-liveness.ts:105-110)
    accepts it because service === "opencodex", and never reads role.
  3. Any management-backed subcommand — ocx models edit, and equally system, access,
    provider, combo, alias — sends its request there through runtimeRequest.
  4. The listener answers the not-served-here 404, which responseMessage
    (src/cli/runtime-api.ts:71-75) renders as the bare token not_found, exiting 4.

Version

dev at a0f611d4aceb9476d44268e43722273b7b211846; originally observed on 2.52.0 in #4662.

Operating system

Platform-independent.

Provider and model

Not provider-specific.

Logs or error output

GET/PUT http://127.0.0.1:10100/api/custom-models/<uuid>
-> 404 {"error":"not_found","method":"PUT","path":"/api/custom-models/<uuid>"}

Screenshots and supporting files

None.

Redacted configuration

A client-role installation with no explicit port override, so both the client listener default
and the standalone proxy default resolve to config.port ?? 10100.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliCLI, config inject, packaging flagsproxyHTTP proxy, routing, reverse-proxy / management auth

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions