Repository navigation
[stable] [flutter_tools] Safely handle broken symlinks and existing files during plugin symlink creation - #194578
Conversation
…ng plugin symlink creation (flutter#191496) ## Description Fixes a crash during plugin symlink creation on Windows/Linux desktop builds (`FileSystemException: Creation failed, OS Error: A file cannot be created if it already exists., errno = 183` / `errno = 17`). ### Cause Previously, `_createPlatformPluginSymlinks` checked `if (link.existsSync()) continue;` before calling `link.createSync(path)`. 1. If a non-link entity (such as a regular directory or file from manual extraction, git checkout, or previous builds) occupied the symlink path, `Link.existsSync()` returned `false`. The tool then called `link.createSync(path)`, crashing with `ERROR_ALREADY_EXISTS` (`errno = 183`) on Windows or `EEXIST` (`errno = 17`) on POSIX. 2. `Link.existsSync()` did not check if an existing symlink pointed to the expected plugin target path. If a plugin's path changed (e.g. a version upgrade in pub cache), existing symlinks pointing to outdated paths were skipped. ### Fix - Uses `typeSync(link.path, followLinks: false)` to inspect disk state type-agnostically before symlink creation. - Canonicalizes and compares `link.targetSync()` with `path`. If matching, creation is skipped. - Deletes stale or mismatched links via `ErrorHandlingFileSystem.deleteIfExists(link)`, and removes conflicting non-link entries before calling `link.createSync(path)`. ## Related Issues * Fixes flutter#90028 * Related to flutter#131978 * Related to flutter#74227 ## Tests - `packages/flutter_tools/test/general.shard/plugins_test.dart`: - `createPluginSymlinks repairs broken symlinks without failing` - `createPluginSymlinks replaces existing files with symlinks without failing`
|
@bkonyi please fill out the PR description above, afterwards the release team will review this request. |
|
This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter. Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed. |
There was a problem hiding this comment.
Code Review
This pull request updates _createPlatformPluginSymlinks in flutter_plugins.dart to inspect disk entities without following links, allowing it to repair broken symlinks or replace conflicting non-link files/directories. Corresponding tests are added to verify these behaviors. Feedback points out that link.existsSync() is redundant after checking the entity type, and that relative symlink targets should be resolved against the symlink's parent directory rather than the current working directory to ensure correct canonicalization.
aa08f09
into
flutter:flutter-3.47-candidate.0
This pull request is created by automatic cherry pick workflow
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.
Issue Link:
#190235
Impact Description:
In Flutter 3.47,
_createPlatformPluginSymlinkscrashes with an unhandledPathExistsException(errno = 183on Windows /errno = 17on macOS and Linux) duringflutter build windows,flutter run -d windows, andflutter pub getwhenever a non-link file or directory occupies a.plugin_symlinks/<plugin>path, and silently skips broken or outdated symlinks after plugin version upgrades. This is a top-10 tool crasher in 3.47.4 (8.2%of allflutter_toolscrashes).Changelog Description:
[flutter/190235] When running
flutter pub getor building desktop apps with existing or broken plugin symlink entries,flutter_toolsno longer crashes with aPathExistsException.Workaround:
Users must manually run
flutter cleanor delete thewindows/flutter/ephemeral/.plugin_symlinksandlinux/flutter/ephemeral/.plugin_symlinksdirectories before runningflutter pub getor building.Risk:
What is the risk level of this cherry-pick?
Test Coverage:
Are you confident that your fix is well-tested by automated tests?
Validation Steps:
windows/flutter/ephemeral/.plugin_symlinks/<plugin>with a regular file or directory, or point the symlink to a non-existent path.flutter pub getorflutter build windowsand verify that the symlink is cleanly replaced without throwing aPathExistsException.