Skip to content

Commit 3faa26f

Browse files
[stable] [flutter_tools] Fix PathNotFoundException during native assets cleanup (#191279)
This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request) Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request. ### Issue Link: #190234 ### Impact Description: During native assets cleanup in `_copyNativeCodeAssetsForOS`, `flutter_tools` iterated over files and called `delete` on each entity. If a file (such as a temporary or OS metadata file) was removed concurrently between listing and deletion, the tool crashed with an unhandled `PathNotFoundException`. This was identified as a top-10 crash signature in Flutter stable release 3.44.8. ### Changelog Description: [flutter/190234] Avoid crashing with PathNotFoundException when cleaning up native assets if files are removed concurrently. ### Workaround: Rerun `flutter clean` or rebuild the application. ### Risk: ### Test Coverage: ### Validation Steps: 1. Build a project using native assets across multiple targets or runs. 2. Verify that cleaning native asset build directories handles missing or transient files gracefully via `deleteIfExists` without throwing `PathNotFoundException`. 3. Run `packages/flutter_tools` unit tests.
1 parent ef055f1 commit 3faa26f

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

‎packages/flutter_tools/lib/src/isolated/native_assets/native_assets.dart‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:logging/logging.dart' as logging;
1212
import 'package:package_config/package_config_types.dart';
1313

1414
import '../../base/common.dart';
15+
import '../../base/error_handling_io.dart';
1516
import '../../base/file_system.dart';
1617
import '../../base/logger.dart';
1718
import '../../base/platform.dart';
@@ -830,8 +831,8 @@ Future<List<File>> _copyNativeCodeAssetsForOS(
830831
if (!targetDir.existsSync()) {
831832
targetDir.createSync(recursive: true);
832833
}
833-
await for (final FileSystemEntity entity in targetDir.list()) {
834-
await entity.delete(recursive: true);
834+
for (final FileSystemEntity entity in await targetDir.list().toList()) {
835+
ErrorHandlingFileSystem.deleteIfExists(entity, recursive: true);
835836
}
836837

837838
if (assetTargetLocations.isEmpty) {

‎packages/flutter_tools/test/general.shard/isolated/native_assets_test.dart‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,50 @@ CMAKE_LINKER:FILEPATH=/usr/bin/ld.ldd
393393
expect(target.didSetCCompilerConfig, isTrue);
394394
},
395395
);
396+
397+
testUsingContext(
398+
'installCodeAssets cleans up existing stale files in target directory without crashing '
399+
'(regression test for https://github.com/flutter/flutter/issues/190234)',
400+
overrides: <Type, Generator>{ProcessManager: () => FakeProcessManager.empty()},
401+
() async {
402+
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
403+
final Uri nonFlutterTesterAssetUri = environment.buildDir
404+
.childFile(InstallCodeAssets.nativeAssetsFilename)
405+
.uri;
406+
await packageConfig.parent.create();
407+
await packageConfig.create();
408+
409+
final environmentDefines = <String, String>{kBuildMode: BuildMode.debug.cliName};
410+
final DartHooksResult dartHookResult = await runFlutterSpecificHooks(
411+
environmentDefines: environmentDefines,
412+
targetPlatform: TargetPlatform.windows_x64,
413+
projectUri: projectUri,
414+
fileSystem: fileSystem,
415+
buildRunner: FakeFlutterNativeAssetsBuildRunner(
416+
packagesWithNativeAssetsResult: <String>['bar'],
417+
),
418+
buildCodeAssets: const BuildCodeAssetsOptions(appBuildDirectory: null),
419+
buildDataAssets: true,
420+
recordedUsesFile: null,
421+
);
422+
final Directory targetDirectory = environment.buildDir.childDirectory('native_assets');
423+
await targetDirectory.create(recursive: true);
424+
final File staleFile = targetDirectory.childFile('stale.txt');
425+
staleFile.writeAsStringSync('stale');
426+
427+
await installCodeAssets(
428+
dartHookResult: dartHookResult,
429+
environmentDefines: environmentDefines,
430+
targetPlatform: TargetPlatform.windows_x64,
431+
projectUri: projectUri,
432+
fileSystem: fileSystem,
433+
nativeAssetsFileUri: nonFlutterTesterAssetUri,
434+
targetUri: targetDirectory.uri,
435+
);
436+
expect(targetDirectory, exists);
437+
expect(staleFile, isNot(exists));
438+
},
439+
);
396440
}
397441

398442
class _SetCCompilerConfigTarget extends FakeFlutterNativeAssetsBuildRunner {

0 commit comments

Comments
 (0)