Symptom
On an old client, ox login prints:
⚠ Deprecation warning: your ox CLI is outdated; run 'ox upgrade' (older versions silently drop telemetry)
But ox upgrade didn't exist until a later release, so the exact users the warning targets hit a dead end:
$ ox upgrade
Error: unknown command "upgrade" for "ox"
Root cause — server-side, not client-side
The deprecation text is entirely server-supplied: the CLI prints whatever string arrives in the X-SageOx-Deprecated response header verbatim (internal/api/version_check.go → PrintDeprecationWarning). No client code constructs this string.
Crucially, the server already knows the client version. Every CLI→server request is built through useragent.NewRequest (internal/useragent/useragent.go), which sets:
User-Agent: ox/<version> (<agent>; <os>; <arch>) e.g. ox/0.5.0 (claude-code; darwin; arm64)
…including the very auth request whose response carries the deprecation header (internal/auth/client.go:144). So the server receives ox/0.5.0, and still tells it to run a command that version doesn't have.
→ This is a pure server bug. There is no client-side ox fix that helps — affected users run old binaries that will never execute new CLI code, and the message is fully server-controlled anyway.
(Correction: an earlier draft of this issue claimed the CLI never sends its version. That was wrong — useragent.NewRequest has always carried ox/<version> in the User-Agent. The server has the data; it just isn't using it to gate the message.)
Fix (server, sageox-mono)
Where the X-SageOx-Deprecated header is set, parse the ox/<ver> token from the request's User-Agent and gate the suggested remediation:
-
Version ≥ the release that introduced ox upgrade → keep "run ox upgrade".
-
Version < that, or no parseable ox/<ver> token (ancient clients sending Go's default UA) → emit the version-agnostic installer instead:
curl -sSL https://raw.githubusercontent.com/sageox/ox/main/scripts/install.sh | bash
The fallback is what actually rescues today's stuck clients.
Related
Same bug class as #608 — guidance pointing at a command surface that doesn't exist on the running client.
Symptom
On an old client,
ox loginprints:But
ox upgradedidn't exist until a later release, so the exact users the warning targets hit a dead end:Root cause — server-side, not client-side
The deprecation text is entirely server-supplied: the CLI prints whatever string arrives in the
X-SageOx-Deprecatedresponse header verbatim (internal/api/version_check.go→PrintDeprecationWarning). No client code constructs this string.Crucially, the server already knows the client version. Every CLI→server request is built through
useragent.NewRequest(internal/useragent/useragent.go), which sets:…including the very auth request whose response carries the deprecation header (
internal/auth/client.go:144). So the server receivesox/0.5.0, and still tells it to run a command that version doesn't have.→ This is a pure server bug. There is no client-side ox fix that helps — affected users run old binaries that will never execute new CLI code, and the message is fully server-controlled anyway.
(Correction: an earlier draft of this issue claimed the CLI never sends its version. That was wrong —
useragent.NewRequesthas always carriedox/<version>in the User-Agent. The server has the data; it just isn't using it to gate the message.)Fix (server, sageox-mono)
Where the
X-SageOx-Deprecatedheader is set, parse theox/<ver>token from the request'sUser-Agentand gate the suggested remediation:Version ≥ the release that introduced
ox upgrade→ keep "runox upgrade".Version < that, or no parseable
ox/<ver>token (ancient clients sending Go's default UA) → emit the version-agnostic installer instead:The fallback is what actually rescues today's stuck clients.
Related
Same bug class as #608 — guidance pointing at a command surface that doesn't exist on the running client.