Skip to content

[Bug]: pnpm-global Codex update installs nothing because @latest resolves under pnpm's minimumReleaseAge #14249

Closed

Description

@Neonsy

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Install Codex globally with pnpm 11 or later using the default minimumReleaseAge (pnpm add -g @openai/codex)
  2. Wait for a new @openai/codex release on npm, then open T3 Code less than a day after it was published
  3. T3 Code reports a Codex update (for me 0.158.0 to 0.159.0, published 2026-09-29 08:14 UTC)
  4. Press update in the app. It reports success, but the update prompt stays
  5. Run the copyable command pnpm add -g @openai/codex@latest. pnpm installs 0.158.0 again. Running pnpm add -g @openai/codex@0.159.0 instead installs 0.159.0

Expected behavior

Pressing update installs the version T3 Code advertises, or T3 Code does not advertise a version pnpm will not install yet

Two options, depending on whether T3 Code should respect pnpm's release-age setting:

  • Pin pnpm-global updates to the advertised version. pnpm then installs it and records the package in minimumReleaseAgeExclude, which bypasses the delay for that version
  • Keep @latest but compare against the newest version older than minimumReleaseAge, so no update is offered until pnpm would install it

Actual behavior

Every update run ends in success, but Codex stays on 0.158.0 and the update prompt stays. There is no error message

pnpm resolves @openai/codex@latest to the newest version older than minimumReleaseAge and exits successfully without mentioning the skipped release. The in-app update and the copyable command both use @latest, so neither T3 Code nor the user learns why nothing changed

T3 Code takes latestVersion from the npm registry's latest tag with no release-age check. makeTargetedProviderUpdateAction in apps/server/src/provider/providerMaintenance.ts can already pin a version, but the pnpm-global update used @latest. This is unchanged on current main and nightly

Impact

Minor bug or occasional failure

Version or commit

v0.0.43-nightly.20260929.2416 @ b21f3b7

Environment

Windows 11 Pro 10.0.26200, T3 Code Nightly desktop, Node 24.21.0, pnpm 12.6.0 (no minimum-release-age override set), Codex CLI 0.158.0 installed with pnpm at %LOCALAPPDATA%\pnpm\bin\codex

Logs or stack traces

Manual run of the copyable command (npm `latest` tag is 0.159.0, published 2026-09-29 08:14 UTC):
$ pnpm add -g @openai/codex@latest
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: %LOCALAPPDATA%\pnpm\store\v11
  Virtual store is at:             AppData/Local/pnpm/global/v11/<hash>/node_modules/.pnpm
.../global/v11/<hash>   | Progress: resolved 2, reused 2, downloaded 0, added 2, done

dependencies:
+ @openai/codex 0.158.0

Done in 403ms using pnpm v12.6.0

Same machine, isolated fresh pnpm home, global installs:
$ pnpm add -g @openai/codex@latest      -> + @openai/codex 0.158.0
$ pnpm add -g @openai/codex@0.159.0     -> + @openai/codex 0.159.0
  and the global package's pnpm-workspace.yaml gains:
  minimumReleaseAgeExclude:
    - '@openai/codex@0.159.0-darwin-arm64 || 0.159.0-darwin-x64 || 0.159.0-linux-arm64 || 0.159.0-linux-x64 || 0.159.0-win32-arm64 || 0.159.0-win32-x64 || 0.159.0'

Server trace (local time), three in-app update presses:
11:33:46 ws.rpc.server.updateProvider 5547ms Success
         ProviderMaintenanceRunner.runCommand 3751ms Success
11:33:59 ws.rpc.server.updateProvider 1543ms Success
         ProviderMaintenanceRunner.runCommand 549ms Success
11:34:15 ws.rpc.server.updateProvider 1719ms Success
         ProviderMaintenanceRunner.runCommand 524ms Success

Cached Codex provider status after the runs:
"updateCommand":"pnpm add -g @openai/codex@latest"
"currentVersion":"0.158.0"
"latestVersion":"0.159.0"
"status":"behind_latest"

Screenshots, recordings, or supporting files

No response

Workaround

Wait until the release is older than minimumReleaseAge, or run pnpm add -g @openai/codex@<version>, which installs it and adds a minimumReleaseAgeExclude entry

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 29, 2026
  2. changed the title [-][Bug]: pnpm-global Codex update silently does nothing while the new release is inside pnpm's minimum release age[/-] [+][Bug]: pnpm-global Codex update installs nothing because `@latest` resolves under pnpm's minimumReleaseAge[/+] on Sep 29, 2026
  3. juliusmarminge commented on Sep 29, 2026

    @juliusmarminge
    Member

    Triage

    Confirmed on current main. Not a duplicate.

    The pnpm-global update is pnpm add -g <package>@latest (resolvePackageManagedProviderMaintenance in apps/server/src/provider/providerMaintenance.ts). The advertised version is the npm latest dist-tag (fetchNpmLatestVersion requests registry.npmjs.org/<package>/latest) with no release-age check. That tag is 0.159.0 for @openai/codex right now.

    pnpm 11+ defaults minimumReleaseAge to 1440 minutes. With no override, that default is non-strict, so @latest resolves to the newest version old enough to pass and the command exits 0 without mentioning the skipped release. That matches this report: updateProvider and runCommand succeed because pnpm exited 0, Codex stays on 0.158.0, and the advisory stays behind_latest, so the prompt stays.

    The in-app result should not be a green "Provider updated". After a zero exit, ProviderMaintenanceRunner marks the update unchanged when the refreshed advisory is still behind_latest, and the toast is the warning "Provider still needs an update". pnpm is the part that prints no reason.

    The ordinary Update button does not pin a version. makeTargetedProviderUpdateAction can rewrite a pnpm-global @latest argument to an exact version, but that only runs when targetVersion is set (the compatibility "install recommended" action). The copyable command is the same @latest string, so running it by hand does the same thing.

    This is every provider installed as a pnpm global, not only Codex. npm and bun also update with @latest, but they do not have this default age gate. Homebrew already avoids the same mismatch by taking latestVersion from brew info instead of npm.

    Closed PR #8363 was about a different pnpm-global failure (install scripts skipped while the command still exits 0). It did not cover release age.

    Both fixes in the report fit the code that is already there:

    No further info needed.

  4. added
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 29, 2026
  5. Neonsy commented on Oct 5, 2026

    @Neonsy
    Author

    Wanted to note that I just saw the manual suggestion command on the currently latest nightly to be:

    PATH-TO PNPM\bin\codex.CMD update

    but that causes the same skip

  6. HerbCaudill commented on Oct 10, 2026

    @HerbCaudill

    Same issue here.

    A workaround is to exclude Codex from pnpm's release-age wait:

    pnpm config set --location=global --json minimumReleaseAgeExclude '["@openai/codex"]'

    This adds the following to your global pnpm config (~/Library/Preferences/pnpm/config.yaml on macOS):

    minimumReleaseAgeExclude:
      - '@openai/codex'

    After that, pnpm add -g @openai/codex@latest installs the newest release right away, and T3's update button works. The tradeoff is that you lose the one-day buffer for Codex. Every other package keeps it.

    If you already have entries in minimumReleaseAgeExclude, add @openai/codex to your existing list. The command above replaces the whole list.

  7. beanow-at-crabnebula commented on Oct 16, 2026

    @beanow-at-crabnebula

    The workaround of minimumReleaseAgeExclude will of course work.

    However I think the preferred solution would be to respect the pnpm policy. There are far too many malware on NPM incidents to discard this very sensible measure that pnpm made the default.

    I would find it rather concerning if T3code was making automatic decisions to grant exceptions for a security-sensitive policy like this too. So I don't think it should add the exception just for the UX paper cut, undermining the security model.

    PNPM itself can confirm whether a provider "still needs updates".

    $ pnpm outdated -g --format json @openai/codex @anthropic-ai/claude-code [...]
    
    {
      "@anthropic-ai/claude-code": {
        "current": "2.1.299",
        "latest": "2.1.300",
        "wanted": "2.1.299",
        "isDeprecated": false,
        "dependencyType": "dependencies"
      }
    }
    

    At the time of writing, 2.1.301 is the actual latest Claude release, but 2.1.300 is the latest that is past for the minimum age threshold.

    This would avoid hard-coding / guessing what the configured age is for your machine. As well as being able to respect any exceptions to the policy, including when it's a particular version range or particular package.

    It looks like #19580 implements exactly that.

  8. juliusmarminge commented on Oct 19, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Fixed by #14295, which just merged: pnpm-global provider updates now install the exact version T3 Code advertises instead of @latest, in both the Update action and the copyable command. Whether updates should instead respect pnpm's release-age delay is being tracked separately in #15329. Closing as completed; it'll ship in the next nightly.

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 is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions