Handle non-existent root directory in PhysicalFilesWatcher#126411
Merged
svick merged 17 commits intodotnet:mainfrom Apr 9, 2026
Merged
Handle non-existent root directory in PhysicalFilesWatcher#126411svick merged 17 commits intodotnet:mainfrom
svick merged 17 commits intodotnet:mainfrom
Conversation
When PhysicalFileProvider is constructed with a root directory that does not yet exist, PhysicalFilesWatcher now defers FileSystemWatcher activation until the root appears. A PendingCreationWatcher monitors the nearest existing ancestor using a non-recursive FileSystemWatcher and cascades through intermediate directory levels as they are created. Once the root directory exists, the main recursive FileSystemWatcher is enabled and any already-existing watched entries are reported. Callers always receive normal FSW-backed change tokens — no re-registration is needed when the root directory appears later. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @dotnet/area-extensions-filesystem |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the Microsoft.Extensions.FileProviders.Physical watcher stack (and related configuration/file-globbing components) to handle roots that don’t exist yet by deferring FileSystemWatcher activation until the directory appears, avoiding broad/incorrect ancestor watching and improving correctness for configuration reload-on-change scenarios.
Changes:
- Add deferred root-creation monitoring to
PhysicalFilesWatcher(including a cascading non-recursive watcher for intermediate directories) and report already-existing entries once the root appears. - Relax
PhysicalFileProviderto allow construction with missing roots; update configuration source resolution to use the file’s immediate parent directory even when missing. - Extend polling and globbing helpers/tests to correctly handle directory paths and missing-directory lifecycles.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/Abstractions/DirectoryInfoWrapper.cs | Refresh DirectoryInfo before checking Exists to avoid stale existence state. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs | Defer FSW enablement until root exists via PendingCreationWatcher, add gap-coverage scan, adjust filtering and error handling. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PollingFileChangeToken.cs | Treat watched path as file or directory (directory fallback) so polling detects directory changes. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs | Allow missing root at construction; centralize separator trimming via PathUtils.PathSeparators; adjust watcher creation. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs | Expose PathSeparators for reuse and make trailing-slash normalization accept both separators. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Resources/Strings.resx | Add new resource strings for missing-root and invalid FSW-path diagnostics. |
| src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs | Resolve provider to the file’s immediate directory (even if missing) and reduce Path to the filename. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs | Add/adjust tests covering missing roots, root recreation, directory tokens, exclusion behavior, and polling variants. |
| src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs | Add test ensuring non-existent roots are accepted; update related watcher tests for robustness. |
| src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/Microsoft.Extensions.Configuration.FileExtensions.Tests.csproj | Include common TempDirectory helper for new test coverage. |
| src/libraries/Microsoft.Extensions.Configuration.FileExtensions/tests/FileConfigurationProviderTest.cs | Integration test verifying token fires when file appears under previously-missing directory. |
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
rosebyte
reviewed
Apr 7, 2026
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Show resolved
Hide resolved
This was referenced Apr 7, 2026
Open
rosebyte
reviewed
Apr 8, 2026
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Outdated
Show resolved
Hide resolved
mrek-msft
reviewed
Apr 8, 2026
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
mrek-msft
reviewed
Apr 8, 2026
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs
Show resolved
Hide resolved
rosebyte
approved these changes
Apr 9, 2026
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.
Handle non-existent root directory in PhysicalFilesWatcher
Fixes #116713
Fixes #107700
Problem
When
PhysicalFileProvideris constructed with a root directory that does not yet exist (e.g., a configuration file path whose parent directory hasn't been created),Watch()fails becauseFileSystemWatchercannot watch a non-existent directory. This commonly occurs withAddJsonFilewhen the config file's parent directory is missing at startup.FileConfigurationSourcehad its own solution: watching the closest existing directory instead. The problem with this is that it commonly watched too much of the system (possibly even all of it), causing significant performance issues.Solution
PhysicalFilesWatchernow gracefully handles a missing root directory by deferringFileSystemWatcheractivation until the root appears. APendingCreationWatchermonitors the nearest existing ancestor directory using a non-recursiveFileSystemWatcherand cascades through intermediate directory levels as they are created. Once the root directory exists, the main recursiveFileSystemWatcheris enabled and any already-existing watched entries are reported.Callers always receive normal FSW-backed change tokens — no re-registration is needed when the root directory appears later.
FileConfigurationSourcethen usesPhysicalFilesWatcheron a directory that may not exist, which is now handled well.Changes
PhysicalFilesWatcher.csPendingCreationWatcherinner class that watches for a non-existent directory to be created.TryEnableFileSystemWatcherdefers toEnsureRootCreationWatcherwhen_rootdoesn't exist, with a callback to retry once it appears.ReportExistingWatchedEntriesfires tokens for entries created before the FSW was active. The constructor normalizes_rootto always have a trailing separator and validates FSW path relationship.OnFileSystemEntryChangenow usesDirectoryInfofor directory paths so exclusion filters work correctly, and guards against events outside_root.OnErrornow also notifies wildcard tokens.PhysicalFileProvider.csDirectoryNotFoundExceptionfor a missing root. UpdatedWatchdoc comments to include directories. Removed duplicate_pathSeparatorsfield in favor ofPathUtils.PathSeparators.FileConfigurationSource.csResolveFileProvidercreates thePhysicalFileProviderwith the file's immediate parent directory (even if missing), relying on the watcher to handle the non-existent case.PollingFileChangeToken.csGetLastWriteTimeUtcnow falls back to checkingDirectoryInfowhenFileInfo.Existsis false, so polling correctly detects directory changes.DirectoryInfois created lazily.PathUtils.csPathSeparatorsmadeinternalfor reuse across files.PhysicalFilesWatcherTests.csFileConfigurationProviderTest.csPhysicalFileProviderTests.csTokenFiredForGlobbingPatternsPointingToSubDirectorypath length issue on .NET Framework.