Hive Hive
Sign in

is not a valid configured external dependency

GitHub issue · Open

Metadata
Source
tuist/tuist #6272
Updated
Jun 11, 2026
Domains
Generated projects
Details

What problem or need do you have?

I am trying to get a very basic setup running, but getting an error generating the project.

I have an app, depending on a local Swift Package, which itself depends on a remote (external) package.

I followed the docs: https://docs.tuist.io/guide/project/dependencies

Ideally I’d like the ‘XcodeProj-based integration’ approach.


MyApp (a SwiiftUI app) |____ MyUI (A local Swift Package - added as a local dependency to MyApp) |____ SnapKit (A third-party package hosted on GitHub - added as an external dependency (GitHub) to MyUI)]


  • When generating just the MyUI Tuist project, it works fine.
  • When generating the MyApp Tuist project, I get error: 'SnapKit' is not a valid configured external dependency.
  • If I remove the dependency on SnapKit, I can generate MyApp successfully.

I tried with other frameworks too, not only SnapKit (like Alamofire, DeepDiff, SDWebImage)

MyApp has Project.swift:

let project = Project(
name: "MyTuistApp",
targets: [
.target(
name: "MyTuistApp",
destinations: .iOS,
product: .app,
sources: ["MyTuistApp/Sources/**"],
dependencies: [
.project(target: "MyUI", path: "./Packages/MyUI"),
]
),
]
)

MyApp has Project.swift:

let project = Project(
name: "MyUI",
targets: [
.target(
name: "MyUI",
destinations: .iOS,
product: .framework,
sources: ["Sources/**"],
dependencies: [
.external(name: "SnapKit")
]
)
]
)

and Package.swift:

let package = Package(
name: "MyUI",
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit", from: "5.0.1")
]
)

Any info would be appreciated, thanks

Potential solution

No response

macOS version

14.1.1

Tuist version

4.9.0

Xcode version

15.2

Comments
S
sovata8 May 15, 2024

Hi, thanks for the reply.

The link to the sample project was a great resource! I took it and reduced it to exactly my reproducible case, and can now observe where things fail.

I am attaching both my sample minimal reproducible project, and the modified Tuist’s app_with_spm_dependencies.

tl;dr: Things work only if the Alamofire package is defined under MyApp’s Package.swift - if we define it in MyFramework’s Package.swift, tuist-generate only works from the framework’s folder, but fails for the whole app. Provided only MyFramework needs to know about the external dependency, ideally we’d like to define the it under MyFramwork, not globally.

The findings

(The explanation here applies to both attached projects, they have been reduced to the same reproducible issue)

So, in both projects MyApp -> MyFramework -> Alamofire.

Both MyApp and MyFramework have a Project.swift. MyApp does not depend on ‘Alamofire’ (directly) only on MyFramework. (Note, this is different from the original app_with_spm_dependencies where both the App and FeatureOne depend directly on Alamofire)

MyFramework’s ‘Project.swift’ has as a target dependency: .project(target: "FeatureOneFramework_iOS", path: .relativeToRoot("Features/FeatureOne"))

MyFramework’s ‘Project.swift’ has as a target dependency: .external(name: "Alamofire")

When it works and when it doesn’t

We need to define the Alamofire package somewhere:

.package(url: "https://github.com/Alamofire/Alamofire", exact: "5.8.0")

If we define it under MyApp/Tuist/Package.swift, things work perfectly - the project generates, builds and runs. Alamofire is only linked to MyFramework as it should. We can also generate and build just MyFramework’s project from its own folder, which is great.

But the above is somewhat confusing / unexpected / not ideal - by defining he package in the main app’s Tuist/Package.swift, we make a ‘hidden’ dependency of MyFramework on a Tuist package defined under MyApp. Indeed, if we take this framework folder and put it elsewhere on our filesystem, it won’t tuist-generate anymore, because the URL for Alamofire was defined in MyApp.

Ideally, we would like to be able to define the Alamofire package under MyFramework/Tuist/Package.swift. Doing this actually works fine when generating MyFramework only, from its folder. But then if we switch to MyApp, the generation fails with:

``Alamofire is not a valid configured external dependency

Zip files

K
krzyzanowskim Aug 13, 2024

I’d like to bump this issue. I encounter the same problem. My setup is similar, only all dependencies are local defined by path ../

T
TamarMilchtaich Sep 2, 2024

Ran into this as well, for a Project inside a Workspace, which seems like it should be a rather common use case. The project is part of the workspace, and is dependent on an external package defined in Workspace/Project/Tuist/Package.swift. Running tuist install then tuist generate from the Project directory - works well, but if you attempt to run it from the Workspace directory, there’s a is not a valid configured external dependency message.

JM
jesus-mg-ios Sep 15, 2024

Same issue

K
kaisegni Nov 25, 2024

Having the same issue

N
Narsail Feb 19, 2025

Same here

P
pepicrft Sep 15, 2025

@sovata8 thanks for putting the reproduction examples together, and apologies for the delayed response.

Tuist has two approaches for dependency integration.

  1. The standard one that Xcode provides where each project has its own set of package dependencies that are resolved by Xcode at runtime
  2. Tuist’s XcodeProj-based integration, where dependencies are resolved with tuist install, and then turned into an Xcode target graph at generation time.

In MyApp_tuist_experiments.zip you are mixing both. The target Modules/MyFramework/Project.swift contains .external(name: "Alamofire"), which is the type 2, and that expects a Package.swift at the root defining the Alamofire dependency. Hence why Tuist says it is not found.

You need to decide for the approach that you want to take and make sure you follow the conventions. This will be useful to make the call. I also adjusted your project to create the two flavours of it. Remember that for 2 you’ll have to run tuist install before.

1.zip, 2.zip

Important

With 2, you have a single source of truth for all your packages, a Package.swift at the root or at Tuist/Package.swift.