Repository navigation
Description
Steps to reproduce
-
Create a pub workspace where the root
pubspec.yamlis a plain Dart package (noflutter:section):# pubspec.yaml name: root_pkg environment: sdk: ^3.11.0 workspace: - apps/app
# apps/app/pubspec.yaml name: app environment: sdk: ">=3.10.0" resolution: workspace dependencies: flutter: sdk: flutter
// apps/app/lib/main.dart import 'package:flutter/material.dart'; void main() => runApp(const MaterialApp(home: Scaffold()));
-
At the workspace root, create an empty
iosdirectory:mkdir ios. -
Run
flutter pub getfrom the workspace root.
Expected results
ios/ stays empty. The root package has no flutter: dependency, so it's not a Flutter project and flutter pub get shouldn't write anything into it.
Actual results
flutter pub get populates ios/ with generated Flutter project files:
ios/Runner/GeneratedPluginRegistrant.h
ios/Runner/GeneratedPluginRegistrant.m
ios/Flutter/flutter_export_environment.sh
ios/Flutter/Generated.xcconfig
ios/Flutter/ephemeral/flutter_lldbinit
ios/Flutter/ephemeral/flutter_lldb_helper.py
ios/Flutter/Generated.xcconfig sets FLUTTER_APPLICATION_PATH to the workspace root itself — a package with no flutter: dependency, no lib/main.dart, no Xcode project.
Root cause
PackagesGetCommand.runCommand (packages/flutter_tools/lib/src/commands/packages.dart) iterates every name in PackageGraph.roots (from .dart_tool/package_graph.json) and unconditionally builds a FlutterProject for each:
for (final String workspaceRootName in graph.roots) {
final Package? rootPackage = packageConfig[workspaceRootName];
...
final FlutterProject project = FlutterProject.fromDirectory(globals.fs.directory(rootUri));
...
await project.regeneratePlatformSpecificTooling(
releaseMode: ignoreReleaseModeSinceItsNotABuildAndHopeItWorks,
);graph.roots includes the pub workspace root package itself, not just its Flutter app members. regeneratePlatformSpecificTooling (packages/flutter_tools/lib/src/project.dart) gates only on whether ios/android directories already exist on disk, not on whether the package declares a flutter: dependency:
Future<void> regeneratePlatformSpecificTooling({...}) async {
return ensureReadyForPlatformSpecificTooling(
androidPlatform: android.existsSync(),
iosPlatform: ios.existsSync(),
...So flutter pub get writes Flutter platform tooling into any ios/android directory sitting at a pub workspace root, whether or not that root package declares a flutter: dependency.
Flutter Doctor output
Flutter 3.41.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 582a0e7c55 (5 months ago) • 2026-02-12 17:12:32 -0800
Engine • hash cc8e596aa65130a0678cc59613ed1c5125184db4 (revision 3452d735bd) (5 months ago) • 2026-02-09 22:03:17.000Z
Tools • Dart 3.11.0 • DevTools 2.54.1
Activity
saurabh-mirajkar commentedon Jul 16, 2026
@ChaserVasya Thanks for the detailed report! I was able to reproduce this behaviour on the latest stable release (
3.44.6).Reproduction Details:
ios/directory at the workspace root causesflutter pub getto generate Flutter platform tooling under the workspace root.android/,macos/, andlinux/directories.web/andwindows/directories were not populated during testing (tested on macOS26.5.2).Labelling and routing this for further investigation.
Skip platform tooling regeneration for non-Flutter pub workspace pack…
[stable] Skip platform tooling regeneration for non-Flutter pub works…
github-actions commentedon Aug 19, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.