Skip to content

fix: trigger full rebuild when a tracked dependency is deleted#20133

Closed
godfengliang wants to merge 2 commits into
tailwindlabs:mainfrom
godfengliang:fix-watch-delete-rebuild
Closed

fix: trigger full rebuild when a tracked dependency is deleted#20133
godfengliang wants to merge 2 commits into
tailwindlabs:mainfrom
godfengliang:fix-watch-delete-rebuild

Conversation

@godfengliang
Copy link
Copy Markdown

Fix

Fixes #20113

Problem

When a file in the CLI watcher's tracked full-rebuild dependency set (e.g., a config dependency like my-color.js) is deleted, the watcher does not trigger a rebuild. This happens because all delete events are unconditionally dropped at L485:

if (event.type === 'delete') return

This means deleting my-color.js (which is imported by tailwind.config.js) silently keeps the stale CSS output instead of surfacing the missing dependency error.

Solution

Instead of unconditionally returning on delete events, add the deleted file path to the tracked files set before returning:

if (event.type === 'delete') {
  files.add(event.path)
  return
}

This allows the handle callback (L260-346) to properly detect deleted files that are in fullRebuildPaths and trigger a full rebuild. The full rebuild will then fail with the appropriate "missing module" error, alerting the user.

Test Plan

Follow the reproduction steps from #20113:

  1. Create a project with tailwind.config.js importing my-color.js
  2. Run tailwindcss --input src/index.css --output dist/out.css --watch
  3. Delete my-color.js

Before fix: No rebuild triggered, stale CSS kept.
After fix: Full rebuild triggered, error about missing my-color.js is shown.

Fixes tailwindlabs#20113

Previously, all delete events were unconditionally dropped in the CLI
watcher. This meant that deleting a config/plugin dependency file would
not trigger a rebuild, leaving stale CSS output.

Now, deleted file paths are still added to the tracked files set so the
handle callback can detect them as full-rebuild paths and trigger a
rebuild that surfaces the missing dependency error.
@godfengliang godfengliang requested a review from a team as a code owner June 1, 2026 08:37
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 1, 2026

Confidence Score: 5/5

Safe to merge — the change is a single-line addition inside the delete-event branch of the watcher, and all existing paths for non-delete events are untouched.

The fix is minimal and surgical: it adds a deleted file's path to the batch set before the early return, then relies entirely on the already-correct handle callback logic to distinguish config deps (full rebuild) from content files (incremental, bails early when no candidates). No new code paths are introduced for the non-delete case, and the debounce/queue flow is unaffected.

No files require special attention.

Reviews (2): Last reviewed commit: "fix: correct comment about deleted file ..." | Re-trigger Greptile

Comment thread packages/@tailwindcss-cli/src/commands/build/index.ts Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 545c4d3f-185b-4cfa-b4c8-2fd9527e9253

📥 Commits

Reviewing files that changed from the base of the PR and between 09daf83 and 1d64663.

📒 Files selected for processing (1)
  • packages/@tailwindcss-cli/src/commands/build/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/@tailwindcss-cli/src/commands/build/index.ts

Walkthrough

The PR updates the build command's file watcher so delete events add the deleted path to the tracked files set instead of being ignored. Deleted content files still hit the candidate cache; deleted config/plugin dependencies are now tracked so a later full rebuild can detect and report missing-file errors.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main fix: triggering a full rebuild when a tracked dependency is deleted.
Description check ✅ Passed The description clearly explains the problem, solution, and test plan, all directly related to the code changes in the PR.
Linked Issues check ✅ Passed The PR correctly addresses issue #20113 by modifying the delete event handler to add the deleted path to the files set, enabling proper rebuild detection and error reporting for missing dependencies.
Out of Scope Changes check ✅ Passed All changes are within scope: the modification to the delete event handler in createWatchers directly addresses the core issue of detecting and rebuilding on tracked dependency deletions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@RobinMalfait
Copy link
Copy Markdown
Member

Hey! Closing this in favor of #20137 where we also make sure that we can recover if you re-add the same file without requiring the write to the input.css file.

Thanks for the PR!

pull Bot pushed a commit to steinsi/Tailwind that referenced this pull request Jun 1, 2026
…cy (tailwindlabs#20137)

This PR fixes an issue where the `@tailwindcss/cli` can get into a
non-recoverable state when any of the transitive dependencies break.

Tailwind CSS has 2 kinds of dependencies:

1. All your templates
2. All dependencies that contribute to your configuration such as the
`input.css`, any plugins, any `tailwind.config.js` files and so on.

When a template changes, we just have to scan for new Tailwind CSS
classes and emit a new CSS file. But when the `input.css` file, or any
of its dependencies changes, then we want to perform a full rebuild.

The idea is that your `@theme` might have changed, or new plugins have
been added, or old plugins have been removed.

If you have an `input.css` file:
```css
@import "tailwindcss";
@config "./tailwind.config.js";
```

That relies on a custom config: `tailwind.config.js`:
```js
const theme = require('./my-custom-theme.js');
module.exports = {
  theme
}
```

If that file relies on yet another file: `./my-custom-theme.js`, then
changes there should also trigger a full rebuild.

Since we're dealing with JavaScript here, we want to clear the require
cache and rebuild the dependency tree such that another change to any of
these files triggers a full fresh build.

However, if any of those (transitive) dependencies are deleted, then we
will end up in an invalid state. Creating a new compiler will result in
a build error. The compiler won't be able to figure out the entire
dependency tree, and we're stuck.

Once the user fixes the potentially missing dependency, the watchers
will not be watching any of those files because we created a fresh
compiler.

With this PR, we fix that by keeping track of old paths and using those
while we are still in an invalid state. The moment everything is fixed,
a fresh dependency tree is created and everything starts working again
without you having to restart the `@tailwindcss/cli` command.

Fixes: tailwindlabs#20113
Closes: tailwindlabs#20114
Closes: tailwindlabs#20133

## Test plan

- Added an integration test that removes the transitive dependency.
Re-adding that file later will recover the CLI state.
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.

CLI watch does not rebuild when a tracked dependency is deleted

2 participants