Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flutter_tools] PathNotFoundException when running flutter create #142537

Open
eliasyishak opened this issue Jan 30, 2024 · 14 comments
Open

[flutter_tools] PathNotFoundException when running flutter create #142537

eliasyishak opened this issue Jan 30, 2024 · 14 comments
Labels
c: crash Stack traces logged to the console P2 Important issues not at the top of the work list team-tool Owned by Flutter Tool team triaged-tool Triaged by Flutter Tool team

Comments

@eliasyishak
Copy link
Contributor

eliasyishak commented Jan 30, 2024

Version: stable/3.16.9
Command: flutter create --template app --overwrite .

PathNotFoundException: PathNotFoundException: Creation failed, path = 'C:\Users\xxxx\Documents\xxxxx\flutter_application_1\lib' (OS Error: The system cannot find the file specified.
, errno = 2)
at _Directory.createSync(directory_impl.dart:129)
at _File.createSync(file_impl.dart:303)
at ForwardingFile.createSync(forwarding_file.dart:26)
at ErrorHandlingFile.createSync.<anonymous closure>(error_handling_io.dart:283)
at _runSync(error_handling_io.dart:590)
at ErrorHandlingFile.createSync(error_handling_io.dart:282)
at Template.render.<anonymous closure>(template.dart:321)
at _LinkedHashMapMixin.forEach(compact_hash.dart:633)
at Template.render(template.dart:281)
at CreateBase.renderMerged(create_base.dart:483)
at <asynchronous gap>(async)
at CreateBase.generateApp(create_base.dart:506)
at <asynchronous gap>(async)
at CreateCommand.runCommand(create.dart:361)
at <asynchronous gap>(async)
at FlutterCommand.run.<anonymous closure>(flutter_command.dart:1367)
at <asynchronous gap>(async)
at AppContext.run.<anonymous closure>(context.dart:150)
at <asynchronous gap>(async)
at CommandRunner.runCommand(command_runner.dart:212)
at <asynchronous gap>(async)
at FlutterCommandRunner.runCommand.<anonymous closure>(flutter_command_runner.dart:348)
at <asynchronous gap>(async)
at AppContext.run.<anonymous closure>(context.dart:150)
at <asynchronous gap>(async)
at FlutterCommandRunner.runCommand(flutter_command_runner.dart:294)
at <asynchronous gap>(async)
at run.<anonymous closure>.<anonymous closure>(runner.dart:112)
at <asynchronous gap>(async)
at AppContext.run.<anonymous closure>(context.dart:150)
at <asynchronous gap>(async)
at main(executable.dart:90)
at <asynchronous gap>(async)
@eliasyishak
Copy link
Contributor Author

As the title suggests, we should catch the error when the user tries to provide a . as the app name in a flutter create command and present them with a warning for the invalid app name.

I could not get this reproduced on my macOS, there may be different behavior on Windows

@eliasyishak eliasyishak added P2 Important issues not at the top of the work list team-tool Owned by Flutter Tool team triaged-tool Triaged by Flutter Tool team labels Jan 30, 2024
@christopherfujino
Copy link
Member

As the title suggests, we should catch the error when the user tries to provide a . as the app name in a flutter create command and present them with a warning for the invalid app name.

I could not get this reproduced on my macOS, there may be different behavior on Windows

It actually looks to me like this is the intended behavior: https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/commands/create_base.dart#L145

And for some reason on Windows we're interpreting this trailing string as project name and NOT project directory.

Now, whether . is a valid Windows relative path I am not sure, however, certainly this seems like the wrong error to throw.

@andrewkolos
Copy link
Contributor

I am unable to repro this on my Windows machine. Looking at recent stack traces, it looks like this is line where this happens:

finalDestinationFile.createSync(recursive: true);

This is surprising, because recursive: true is specified, so I would not expect to see The system cannot find the file specified. I wonder if I'm making a mistake here.

@andrewkolos
Copy link
Contributor

andrewkolos commented Jun 13, 2024

Looking at the implementations of _File::createSync (and _Directory::createSync), the only thing I could possibly imagine is that the project root directory is getting deleted as we try to write lib/main.dart, but I feel like this situation would be exceedingly rare unless the tool was doing something wrong. This is why I haven't written a PR that just catches this exception and exits the tool.

@christopherfujino
Copy link
Member

Looking at the implementations of _File::createSync (and _Directory::createSync), the only thing I could possibly imagine is that the project root directory is getting deleted as we try to write lib/main.dart, but I feel like this situation would be exceedingly rare unless the tool was doing something wrong. This is why I haven't written a PR that just catches this exception and exits the tool.

Could be anti-virus software quarantining it soon after it's created.

@andrewkolos
Copy link
Contributor

andrewkolos commented Jun 13, 2024

Could be anti-virus software quarantining it soon after it's created.

With flutter create ., the project directory already exists (the current working directory), unless it's somehow being moved/deleted between the start of flutter create . and the call to create the lib directory.

EDIT: I see crash reports where . isn't used as the project, so nevermind this.

@andrewkolos andrewkolos changed the title [flutter_tools] PathNotFoundException when running flutter create with . as the app name [flutter_tools] PathNotFoundException when running flutter create . Jun 13, 2024
@andrewkolos
Copy link
Contributor

cc: @brianquinlan

@brianquinlan
Copy link
Contributor

The docs for CreateDirectoryW say:

ERROR_PATH_NOT_FOUND: One or more intermediate directories do not exist; this function will only create the final directory in the path.

@andrewkolos andrewkolos changed the title [flutter_tools] PathNotFoundException when running flutter create . [flutter_tools] PathNotFoundException when running flutter create Jun 13, 2024
@brianquinlan
Copy link
Contributor

The implementation of Directory.createSync is:

  void createSync({bool recursive = false}) {
    if (recursive) {
      if (existsSync()) return;
      if (path != parent.path) {
        parent.createSync(recursive: true);
      }
    }
    var result = _create(_Namespace._namespace, _rawPath);
    if (result is OSError) {
      throw FileSystemException._fromOSError(result, "Creation failed", path);
    }
  }

So the only way that I can see how this would happen is if a parent directory is deleted between the time createSync is called and CreateDirectoryW is executed. It seems pretty unlikely that that would happen with any non-trivial frequency though.

@aam
Copy link
Member

aam commented Jun 13, 2024

Deleting single file with recursive: true

finalDestinationFile.deleteSync(recursive: true);
seems suspicious. I don't think we want to specify recursive: true when we delete single file.

@andrewkolos
Copy link
Contributor

andrewkolos commented Jun 13, 2024

Had some conversation with @brianquinlan and @aam (thanks folks!) where we discussed some fun theories, but we ultimately didn't come up with anything to explain how this could happen.

I see a couple ways forward from here:

  1. Hope a user finds and shares a way to repro this that works on one of our machines.
  2. Find a way to query exactly when this crash first was first reported by the CLI tool (assuming this is even possible), and look for any suspicious changes to flutter create logic (or perhaps changes to dart:io) that happened around this time

@aam
Copy link
Member

aam commented Jun 13, 2024

Note that this behavior goes back to at least 2021: #65242 (comment).

Also note that #63540 improved user experience around various file access errors during project creation. Perhaps that could be extended over this file creation/direction creation.

@andrewkolos
Copy link
Contributor

Note that this behavior goes back to at least 2021: #65242 (comment).

Thanks for digging this up!

Also note that #63540 improved user experience around various file access errors during project creation. Perhaps that could be extended over this file creation/direction creation.

Yeah, I think it's fair in situations like these (where we are truly stumped) to simply catch this exception and exit gracefully with a helpful message. If doing so ends up masking a legitimate bug in the tool, then we could still hope that there is a user out there willing to engage with us inside a new GitHub issue.

@andrewkolos andrewkolos self-assigned this Jun 13, 2024
@andrewkolos
Copy link
Contributor

andrewkolos commented Jun 26, 2024

Unassigning since I don't have high confidence that I will be fixing this within the next two weeks. I think another solution to this issue would be to augment ErrorHandlingFile.create(Sync) and ErrorHandlingDirectory.create(Sync) to call throwToolExit when a PathNotFoundException is encountered and we know recursive is set to true. If this route is chosen, this would probably involve a non-trivial refactor to the corresponding helper functions, _run and _runSync to able to accept additional error-handling functions that the create(Sync) methods would use to handle these errors when recursive is set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: crash Stack traces logged to the console P2 Important issues not at the top of the work list team-tool Owned by Flutter Tool team triaged-tool Triaged by Flutter Tool team
Projects
None yet
5 participants