Skip to content

Turbopack: Add support for specifying additional roots - #98003

Draft
bgw wants to merge 25 commits into
canaryfrom
bgw/additional-roots
Draft

Turbopack: Add support for specifying additional roots#98003
bgw wants to merge 25 commits into
canaryfrom
bgw/additional-roots

Conversation

@bgw

@bgw bgw commented Aug 27, 2026

Copy link
Copy Markdown
Member

Full motivation and plan here: https://app.notion.com/p/vercel/Turbopack-pnpm-Global-Virtual-Store-383e06b059c480579403ddfd71cc2d40?source=copy_link

The goal is to allow DiskFileSystem to traverse outside of it's own root to other configured DiskFileSystems when following symlinks. We may allow traversal in other situations in the future, but this is limited to symlink resolution for now.

Global Virtual Store

The motivation for this is to enable pnpm's Global Virtual Store feature (and there are other package managers doing this, including nub and bun).

We'd expose the ability to manually configure this in next.config.js, but we should also auto-configure ourselves for popular package managers (or at least make a best effort to do so, the PNPM_HOME semantics can be complicated). The ignoreIfMissing option is provided for this situation: We can configure a bunch of roots automatically, and they only actually get set up if they exist, the check for directory existence is cheap.

Open questions

  • We emit the error late, when reading the project, rather than when constructing it. This leads to duplicate reported warnings every time we read from the project, rather than giving one warning during initial startup. We must do this because Issue requires a file path. Arguably the right file path here is the next.config.js file, though right now we're using the project root. If we lifted the path requirement from Issue, we could construct the error earlier.
    • Add a barrier to State to avoid issues with invalidations with no caching enabled, which causes invalidations to be disabled
    • ProjectContainer::initialize is not a turbo-task function, so we can actually move the canonicalization into initialize after the project DiskFileSystem is constructed.
  • The additionalRoots config is not experimental. Should it be experimental?
  • We use State for mutating the DiskFileSystemMap stored on DiskFileSystemInner. Is there any better way we should be doing this?
    • Sadly, I don't think so -- not without a much more awkward API that requires that callers track and pass around a Vc<DiskFileSystemMap> themselves.

bgw added 25 commits August 27, 2026 13:30
… config

- The Next config is parsed inside a turbo-tasks function, which is too
  late, pass it in as separate NAPI object as part of the project
  options.
- Improve error handling and formatting of AdditionalRootIssue
- AdditionalRootConfig::canonicalize returns a Result instead of an
  Option
- The handling of 'optional' moves out of
  `AdditionalRootConfig::canonizalize` and into the callsite
- If something doesn't implement Issue call it Error instead.
- Rename AdditionalRootConfigIsssue to AdditionalRootIssue
- Don't flatten AdditionalRootError into AdditionalRootIssue
…rust at all, the js callers already do this for us
…lean up constructor, add nicer DiskFileSystemMap::empty API
@bgw
bgw requested a review from lukesandberg August 27, 2026 23:03
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Failing test suites

Commit: 276c31f | About building and testing Next.js

pnpm test-start-experimental-turbo test/e2e/filesystem-cache/filesystem-cache.test.ts (turbopack) (Experimental) (job)

  • filesystem-caching with cache disabled > should cache or not cache loaders (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RSC change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RCC change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (Pages change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (rename app page) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (next config change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (env var change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RSC change, RCC change, Pages change, rename app page, next config change, env var change) (DD)
Expand output

● filesystem-caching with cache disabled › should cache or not cache loaders

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should cache or not cache loaders

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should cache or not cache loaders

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (env var change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (env var change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next)

... truncated ...

pnpm test-start-experimental-turbo test/e2e/twoslash/standalone.test.ts (turbopack) (Experimental) (job)

  • output: standalone with twoslash > should annotate twoslash types esnext (DD)
Expand output

● output: standalone with twoslash › should annotate twoslash types esnext

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `output: standalone with twoslash should annotate twoslash types esnext 1`

- Snapshot  - 34
+ Received  + 12

  {
-   "code": "type X = Promise<number>;
- 'hello'.toUpperCase()",
-   "error": undefined,
-   "nodes": [
-     {
-       "character": 5,
-       "length": 1,
-       "line": 0,
-       "start": 5,
-       "target": "X",
-       "text": "type X = Promise<number>",
-       "type": "hover",
-     },
-     {
-       "character": 9,
-       "docs": "Represents the completion of an asynchronous operation",
-       "length": 7,
-       "line": 0,
-       "start": 9,
-       "target": "Promise",
-       "text": "interface Promise<T>",
-       "type": "hover",
-     },
-     {
-       "character": 8,
-       "docs": "Converts all the alphabetic characters in a string to uppercase.",
-       "length": 11,
-       "line": 1,
-       "start": 34,
-       "target": "toUpperCase",
-       "text": "(method) String.toUpperCase(): string",
-       "type": "hover",
-     },
-   ],
+   "code": undefined,
+   "error": {
+     "description": "These errors were not marked as being expected: 2583 2339. 
+ Expected: // @errors: 2583 2339",
+     "recommendation": "Compiler Errors:
+
+ index.ts
+   [2583] 9 - Cannot find name 'Promise'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
+   [2339] 34 - Property 'toUpperCase' does not exist on type '"hello"'.",
+     "title": "Errors were thrown in the sample, but not included in an error tag",
+   },
+   "nodes": undefined,
  }

  73 |           await fetchViaHTTP(appPort, `/?${mode}`)
  74 |         ).json()
> 75 |         expect({ code, nodes, error }).toMatchInlineSnapshot(`
     |                                        ^
  76 |            {
  77 |              "code": "type X = Promise<number>;
  78 |            'hello'.toUpperCase()",

  at toMatchInlineSnapshot (e2e/twoslash/standalone.test.ts:75:40)

pnpm test-dev test/e2e/app-dir/actions/app-action-node-middleware.test.ts (job)

  • app-dir action handling > HMR > should support updating the action (DD)
Expand output

● app-dir action handling › HMR › should support updating the action

expect(received).toBeGreaterThan(expected)

Expected: > 1000
Received:   1000

  1052 |             await browser.elementByCss('#inc').click()
  1053 |             const val = Number(await browser.elementById('count').text())
> 1054 |             expect(val).toBeGreaterThan(1000)
       |                         ^
  1055 |           })
  1056 |         } finally {
  1057 |           await next.patchFile(filePath, origContent)

  at toBeGreaterThan (e2e/app-dir/actions/app-action.test.ts:1054:25)
  at retry (lib/next-test-utils.ts:871:14)
  at Object.<anonymous> (e2e/app-dir/actions/app-action.test.ts:1051:11)

pnpm test-deploy test/e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts (job)

  • turbopack additional roots > resolves a linked package, sibling dependency, and next/dist (DD)
Expand output

● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist

Failed to deploy project https://vtest314-e2e-tests-r2kjohv44-vtest314-next-adapter-e2e-tests.vercel.app undefined (1)

  503 |
  504 |     if (deployRes.exitCode !== 0) {
> 505 |       throw new Error(
      |             ^
  506 |         `Failed to deploy project ${deployRes.stdout} ${deployRes.stderr} (${deployRes.exitCode})`
  507 |       )
  508 |     }

  at NextDeployInstance.setup (lib/next-modes/next-deploy.ts:505:13)
  at lib/e2e-utils/index.ts:314:7
  at Span.traceAsyncFn (../packages/next/src/trace/trace.ts:146:14)
  at createNext (lib/e2e-utils/index.ts:278:12)
  at Object.<anonymous> (lib/e2e-utils/index.ts:387:16)

● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at Object.testDir (e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts:29:40)

● Test suite failed to run

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at Object.stop (e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts:47:18)

pnpm test-deploy-experimental-turbo test/e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts (turbopack) (Experimental) (job)

  • turbopack additional roots > resolves a linked package, sibling dependency, and next/dist (DD)
Expand output

● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist

Failed to deploy project https://vtest314-e2e-tests-cny4n9drp-vtest314-next-adapter-e2e-tests.vercel.app undefined (1)

  503 |
  504 |     if (deployRes.exitCode !== 0) {
> 505 |       throw new Error(
      |             ^
  506 |         `Failed to deploy project ${deployRes.stdout} ${deployRes.stderr} (${deployRes.exitCode})`
  507 |       )
  508 |     }

  at NextDeployInstance.setup (lib/next-modes/next-deploy.ts:505:13)
  at lib/e2e-utils/index.ts:314:7
  at Span.traceAsyncFn (../packages/next/src/trace/trace.ts:146:14)
  at createNext (lib/e2e-utils/index.ts:278:12)
  at Object.<anonymous> (lib/e2e-utils/index.ts:387:16)

● turbopack additional roots › resolves a linked package, sibling dependency, and next/dist

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at Object.testDir (e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts:29:40)

● Test suite failed to run

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at Object.stop (e2e/app-dir/turbopack-additional-roots/turbopack-additional-roots.test.ts:47:18)

pnpm test-start-turbo test/e2e/filesystem-cache/filesystem-cache.test.ts (turbopack) (job)

  • filesystem-caching with cache disabled > should cache or not cache loaders (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RSC change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RCC change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (Pages change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (rename app page) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (next config change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (env var change) (DD)
  • filesystem-caching with cache disabled > should allow to change files while stopped (RSC change, RCC change, Pages change, rename app page, next config change, env var change) (DD)
Expand output

● filesystem-caching with cache disabled › should cache or not cache loaders

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should cache or not cache loaders

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should cache or not cache loaders

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (RSC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (RCC change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (Pages change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (rename app page)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next) {
> 467 |         throw new Error(
      |               ^
  468 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  469 |         )
  470 |       }

  at Object.set (lib/e2e-utils/index.ts:467:15)
  at Object.<anonymous> (e2e/filesystem-cache/filesystem-cache.test.ts:74:53)

● filesystem-caching with cache disabled › should allow to change files while stopped (next config change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  456 |     get: function (_target, property) {
  457 |       if (!next) {
> 458 |         throw new Error(
      |               ^
  459 |           'next instance is not initialized yet, make sure you call methods on next instance in test body.'
  460 |         )
  461 |       }

  at Object.get (lib/e2e-utils/index.ts:458:15)
  at stop (e2e/filesystem-cache/filesystem-cache.test.ts:93:18)
  at Object.stop (e2e/filesystem-cache/filesystem-cache.test.ts:114:13)

● filesystem-caching with cache disabled › should allow to change files while stopped (env var change)

next build failed with code/signal 1

  137 |             if (code || signal)
  138 |               reject(
> 139 |                 new Error(
      |                 ^
  140 |                   `next build failed with code/signal ${code || signal}`
  141 |                 )
  142 |               )

  at ChildProcess.<anonymous> (lib/next-modes/next-start.ts:139:17)

● filesystem-caching with cache disabled › should allow to change files while stopped (env var change)

next instance is not initialized yet, make sure you call methods on next instance in test body.

  465 |     set: function (_target, key, value) {
  466 |       if (!next)

... truncated ...

pnpm test-start-turbo test/e2e/twoslash/standalone.test.ts (turbopack) (job)

  • output: standalone with twoslash > should annotate twoslash types esnext (DD)
Expand output

● output: standalone with twoslash › should annotate twoslash types esnext

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `output: standalone with twoslash should annotate twoslash types esnext 1`

- Snapshot  - 34
+ Received  + 12

  {
-   "code": "type X = Promise<number>;
- 'hello'.toUpperCase()",
-   "error": undefined,
-   "nodes": [
-     {
-       "character": 5,
-       "length": 1,
-       "line": 0,
-       "start": 5,
-       "target": "X",
-       "text": "type X = Promise<number>",
-       "type": "hover",
-     },
-     {
-       "character": 9,
-       "docs": "Represents the completion of an asynchronous operation",
-       "length": 7,
-       "line": 0,
-       "start": 9,
-       "target": "Promise",
-       "text": "interface Promise<T>",
-       "type": "hover",
-     },
-     {
-       "character": 8,
-       "docs": "Converts all the alphabetic characters in a string to uppercase.",
-       "length": 11,
-       "line": 1,
-       "start": 34,
-       "target": "toUpperCase",
-       "text": "(method) String.toUpperCase(): string",
-       "type": "hover",
-     },
-   ],
+   "code": undefined,
+   "error": {
+     "description": "These errors were not marked as being expected: 2583 2339. 
+ Expected: // @errors: 2583 2339",
+     "recommendation": "Compiler Errors:
+
+ index.ts
+   [2583] 9 - Cannot find name 'Promise'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
+   [2339] 34 - Property 'toUpperCase' does not exist on type '"hello"'.",
+     "title": "Errors were thrown in the sample, but not included in an error tag",
+   },
+   "nodes": undefined,
  }

  73 |           await fetchViaHTTP(appPort, `/?${mode}`)
  74 |         ).json()
> 75 |         expect({ code, nodes, error }).toMatchInlineSnapshot(`
     |                                        ^
  76 |            {
  77 |              "code": "type X = Promise<number>;
  78 |            'hello'.toUpperCase()",

  at toMatchInlineSnapshot (e2e/twoslash/standalone.test.ts:75:40)

Other failing CI jobs

Comment on lines +81 to +83
bail!("Cannot read directory as file content: {target_fs_path}")
}
_ => bail!("Invalid cross-filesystem symlink target"),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't want to bail here

Comment on lines +683 to +698
async fn canonicalize_untracked(sys_path: RcStr) -> Vc<OptionRcStr> {
Vc::cell(
retry_blocking(|| canonicalize_to_rcstr(Path::new(&*sys_path)))
.await
.ok(),
)
}

let ancestors: SmallVec<[&Path; 8]> = target_sys_path.ancestors().collect();
for prefix in ancestors.into_iter().rev().skip(1) {
let Some(prefix_str) = prefix.to_str() else {
return Ok(None);
};
let Some(canonical) = canonicalize_untracked(RcStr::from(prefix_str))
.owned()
.await?

@bgw bgw Aug 27, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some comments about how this is similar to resolve_link_target_ancestry_slow_path, or figure out a better way to share code between these two places.

Possible future follow-up PR: I'd also like to just optimize this pattern a bit better, but it'll involve hacking around turbo-tasks in some unsafe ways.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant