Skip to content

fix(deps): guard against undefined deps in commitProcessing#21816

Open
guest363 wants to merge 1 commit intovitejs:mainfrom
guest363:fix/optimizer-commit-processing-undefined-access
Open

fix(deps): guard against undefined deps in commitProcessing#21816
guest363 wants to merge 1 commit intovitejs:mainfrom
guest363:fix/optimizer-commit-processing-undefined-access

Conversation

@guest363
Copy link

When the dependency optimizer re-runs during dev startup (e.g. due to virtual module content changes), commitProcessing may encounter deps in newData.optimized that don't exist in metadata.optimized/discovered, or deps in metadata.optimized that were removed from newData.optimized.

This adds null guards to prevent TypeError when accessing browserHash and fileHash on undefined entries.

When the dependency optimizer re-runs during dev startup (e.g. due to
virtual module content changes), commitProcessing may encounter deps in
newData.optimized that don't exist in metadata.optimized/discovered, or
deps in metadata.optimized that were removed from newData.optimized.

This adds null guards to prevent TypeError when accessing browserHash
and fileHash on undefined entries.

Closes #XXXX
@bluwy
Copy link
Member

bluwy commented Mar 13, 2026

So I can understand better, does this fixes a bug you're encountering in a project? Or are these changes only hypothetical?

@guest363
Copy link
Author

Yes, this fixes a real bug I'm encountering in my project. I hit it while migrating to Astro 6, which introduced a new Font API using fontProviders.local().

Root cause chain (my assumption):

  1. Astro's FsFontFileContentResolver reads binary font files (.woff2, .woff, .ttf) via readFileSync(path, 'utf-8'), which likely produces unstable hashes for binary content.
  2. Unstable hashes cause the virtual font module content to change between optimizer runs.
  3. Vite detects the change and triggers a re-optimization.
  4. During commitProcessing, a dependency can exist in newData.optimized but not in metadata.optimized or metadata.discovered - this causes the TypeError: Cannot read properties of undefined (reading 'browserHash') / TypeError: Cannot read properties of undefined (reading 'fileHash').

While the upstream root cause is on the Astro side, the Vite optimizer should still be resilient here - a dep appearing in new optimization results without a corresponding entry in previous metadata is a valid edge case that shouldn't crash the server. These guards make commitProcessing defensive against any scenario where the dep sets don't fully overlap.

@guest363
Copy link
Author

I've verified this fix in my project using yarn patch - the error that was consistently occurring is completely gone.

@guest363
Copy link
Author

Vite 8 does not repeat the error

@bluwy
Copy link
Member

bluwy commented Mar 19, 2026

a dep appearing in new optimization results without a corresponding entry in previous metadata is a valid edge case that shouldn't crash the server. These guards make commitProcessing defensive against any scenario where the dep sets don't fully overlap.

I think what you said makes sense, but I'm wary that adding this is guarding against a case that shouldn't happen in the first place, and could cause other bugs in the future. For example:

a dependency can exist in newData.optimized but not in metadata.optimized or metadata.discovered

I believe the flow here is that the metadata (previous run) would discover new deps as it runs (places into .discovered), so in newData (next run) its optimized deps will for sure be either in the previous' runs optimized list or discovered list.

So perhaps the root cause is in a different place, and it seems a bit like a race condition somewhere with your description. I think it's worth tracking this down if possible, otherwise if you can share your project/repro/setup that would be valuable too. If the other maintainers are fine with this PR, I'm also good with that, but I'd lean towards understanding the edgecase better first.

@bluwy bluwy added p2-edge-case Bug, but has workaround or limited in scope (priority) feat: deps optimizer Esbuild Dependencies Optimization labels Mar 19, 2026
@guest363
Copy link
Author

@bluwy Thank you for the thorough explanation - you're absolutely right that the invariant should hold by design, and guarding against it could mask real issues down the road rather than solving them.

Since I've confirmed that Vite 8 fully resolves this issue (verified by removing my v7 patch and upgrading to v8 in my project), I don't think it's worth spending more time tracking down the exact race condition in v7. Closing this PR.

Thanks for your time and patience reviewing this! 🙏

@guest363 guest363 closed this Mar 19, 2026
@guest363
Copy link
Author

@bluwy I need to reopen this - apologies for closing prematurely. I didn't properly remove my yarn patch when testing with Vite 8, so the results were misleading. After fully removing the patch and upgrading to Vite 8, the bug reproduces consistently.

Following your suggestion to understand the edge case better, I added debug logging to commitProcessing() to capture exactly what's happening:

[vite] Re-optimizing dependencies because vite config has changed
[vite:deps] INVARIANT VIOLATION: dep "astro/actions/runtime/entrypoints/route.js"
  exists in newData.optimized but not in metadata.optimized or metadata.discovered
  newData.optimized keys: [ 'astro/actions/runtime/entrypoints/route.js' ]
  metadata.optimized keys: []
  metadata.discovered keys: [
    'react', 'react-dom', 'react-dom/client',
    '@astrojs/react/client.js', '@astrojs/svelte/client.js',
    'svelte', 'svelte/animate', 'svelte/internal',
    'svelte/internal/client', ... (25+ deps)
  ]

So my initial assumption about fonts was wrong - the actual culprit is astro/actions/runtime/entrypoints/route.js. It appears in newData.optimized but was never registered in metadata.optimized or metadata.discovered. It seems like Astro's Actions plugin injects this dependency into the optimizer in a way that bypasses Vite's normal discovery flow, likely during a config change that triggers re-optimization.

I haven't been able to reproduce this in a clean minimal repo yet - it may require a specific combination of integrations (React + Svelte + Actions in my case). I'll keep working on isolating a minimal repro.

@guest363 guest363 reopened this Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat: deps optimizer Esbuild Dependencies Optimization p2-edge-case Bug, but has workaround or limited in scope (priority)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants