fix: Detect scoped @turbo/{platform} packages in local binary resolution#12386
Merged
anthonyshew merged 2 commits intovercel:mainfrom Mar 18, 2026
Merged
Conversation
…ution
The per-platform npm packages were renamed from `turbo-{platform}`
to `@turbo/{platform}` in 2.8.18-canary.3, but the shim still
searched for the old unscoped names, causing it to fall back to the
global binary with a spurious warning.
Contributor
|
Someone is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
- Fix generate_unplugged_path to support scoped package names in Berry PnP unplugged directories (was hardcoded to legacy format only) - Fix early-return via ? operator that aborted the entire search when one root had a malformed package.json (now continues to next candidate) - Restructure infer() to interleave scoped/legacy per search root, halving worst-case filesystem I/O during migration period - Add 7 integration tests for infer() covering hoisted, unplugged, fallback, priority ordering, and malformed package.json resilience - Replace tautological turbo_state tests with meaningful invariant check - Restore removed comments explaining search ordering and design rationale
@turbo/{platform} packages in local binary resolution@turbo/{platform} packages in local binary resolution
anthonyshew
approved these changes
Mar 18, 2026
Contributor
anthonyshew
left a comment
There was a problem hiding this comment.
Oops, what a blunder by me! Thank you for calling this to my attention.
I reworked a little bit of yours to turn it into what we'll merge. Thank you!
anthonyshew
added a commit
that referenced
this pull request
Mar 18, 2026
The Rust shim was updated in #12386 to resolve both @turbo/<platform> and turbo-<platform> packages, but the Node shim (packages/turbo/bin/turbo) still only resolves @turbo/* names. Users upgrading across the 2.8.17 → 2.8.18 scope rename boundary can have legacy turbo-<platform> binaries in node_modules that the Node shim silently ignores. Add binaryPaths/packageNames/tryResolve helpers so every resolution step (direct, JIT install, emulated, diagnostics, lockfile check) tries the scoped name first and falls back to the legacy unscoped name. Closes #10618
anthonyshew
added a commit
that referenced
this pull request
Mar 18, 2026
## Summary - The Node shim (`packages/turbo/bin/turbo`) only resolves `@turbo/<platform>` packages. Users upgrading across the 2.8.17 → 2.8.18 scope rename boundary can have legacy `turbo-<platform>` binaries in `node_modules` that the shim silently ignores, falling through to a slow JIT `npm install` or failing entirely. - Add `binaryPaths`/`packageNames`/`tryResolve` helpers so every resolution step (direct, JIT install, emulated, diagnostics, lockfile check) tries the scoped name first then falls back to the legacy unscoped name. This is the Node-side counterpart to #12386, which fixed the same gap in the Rust shim. ## How to test ```bash mkdir /tmp/turbo-test && cd /tmp/turbo-test && npm init -y # Install last version with unscoped names npm install turbo@2.8.17 # Swap in the patched shim cp <repo>/packages/turbo/bin/turbo node_modules/turbo/bin/turbo # Should resolve the legacy binary without JIT install npx turbo --version ``` Closes #10618
github-actions Bot
added a commit
that referenced
this pull request
Mar 18, 2026
## Release v2.8.19 Versioned docs: https://v2-8-19.turborepo.dev ### Changes - release(turborepo): 2.8.18 (#12378) (`0afc24f`) - fix: Use previous stable tag for stable release notes (#12379) (`3e2b9bb`) - fix: Remove unnecessary git pull in update-examples workflow (#12380) (`97367ec`) - ci: Use blobless clones for release workflow checkouts (#12381) (`84a5369`) - release(turborepo): 2.8.19-canary.1 (#12383) (`f9517de`) - feat: Deprecate `turbo-ignore` in favor of `turbo query affected` (#12382) (`1b9f6cb`) - release(turborepo): 2.8.19-canary.2 (#12384) (`1885f08`) - fix: Tailored `turbo-ignore` deprecation notice for Vercel users (#12385) (`4b2eae6`) - release(turborepo): 2.8.19-canary.3 (#12387) (`ee90d8e`) - chore: Upgrade Next.js to 16.2.0 in examples and apps (#12389) (`2ff8fc9`) - fix: Detect scoped `@turbo/{platform}` packages in local binary resolution (#12386) (`9d977f1`) - fix: Support legacy unscoped binary package names in Node shim (#12391) (`7da779a`) --------- Co-authored-by: Turbobot <turbobot@vercel.com>
github-actions Bot
added a commit
that referenced
this pull request
Mar 19, 2026
## Release v2.8.20-canary.1 Versioned docs: https://v2-8-20-canary-1.turborepo.dev ### Changes - release(turborepo): 2.8.19-canary.3 (#12387) (`ee90d8e`) - chore: Upgrade Next.js to 16.2.0 in examples and apps (#12389) (`2ff8fc9`) - fix: Detect scoped `@turbo/{platform}` packages in local binary resolution (#12386) (`9d977f1`) - fix: Support legacy unscoped binary package names in Node shim (#12391) (`7da779a`) - release(turborepo): 2.8.19 (#12392) (`66f2c36`) - fix: Prevent `stdin` from being dropped for persistent tasks in stream mode (#12394) (`106fa3e`) Co-authored-by: Turbobot <turbobot@vercel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
generate_unplugged_pathto detect scoped@turbo/{platform}packages in Berry PnP unplugged directories (was hardcoded to legacyturbo-{platform}only)?operator inside the search loop that silently aborted the entire binary resolution when one search root had a malformedpackage.jsoninfer()to interleave scoped/legacy probing per search root, halving worst-case filesystem I/O during the migration periodinfer()covering hoisted, unplugged, fallback, priority ordering, and error resilienceContext
The initial commit extracted
try_find_with_package_pathto support both@turbo/{platform}and legacyturbo-{platform}formats. A review found three issues:Unplugged bug:
generate_unplugged_pathhardcoded the legacy package name prefix for Berry's directory matching, so scoped packages in Berry PnP would silently fall back to global turbo.Early-return bug (pre-existing, amplified): The
?operator onPackageJson::load().ok()?returnedNonefrom the entire search function instead of continuing to the next search root. A brokenpackage.jsonat one root killed discovery of valid installs at other roots.Doubled I/O: The
or_elsestructure ran all 4 search strategies for scoped, then all 4 again for legacy. Restructuring to try both formats per root reuses eachgenerate_*_pathresult and avoids redundant.yarnrc.ymlparsing.Testing
The
infer()public API previously had zero test coverage. This adds tempdir-based integration tests that create mock package layouts and verify resolution:test_infer_hoisted_scoped/test_infer_hoisted_legacy_fallbacktest_infer_scoped_preferred_over_legacy— verifies priority orderingtest_infer_malformed_package_json_continues_search— verifies the?fixtest_infer_unplugged_scoped/test_infer_unplugged_legacy— verifies the Berry fixtest_infer_empty_dir_returns_noneRun with
cargo test -p turborepo-shim.