What does this dependency resolution error mean?

i get this error when i try to resolve dependencies for a package with a direct and transitive dependency on SwiftSyntax:

Dependencies could not be resolved because root depends on 'swift-dom' 1.0.1..<1.1.0 and root depends on 'swift-syntax' 600.0.0-prerelease-2024-05-28.
'swift-dom' >= 1.0.1 practically depends on 'swift-syntax' 510.0.1..<601.0.0 because 'swift-dom' 1.0.1 depends on 'swift-syntax' 510.0.1..<601.0.0 and no versions of 'swift-dom' match the requirement 1.0.2..<1.1.0.

under semver sort order, doesn’t 600.0.0-prerelease-2024-05-28 fall within the range 510.0.1 ..< 601.0.0?

2 Likes

I'm pretty sure SPM (and CocoaPods IIRC) only support alpha, beta, and rc pre-release names, which are technically implementation-defined in semver. But even if it did, I've never seen it consider such a version when the version range consists of only release versions, as it takes semver's warning literally:

A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.

This is probably a reasonable behavior, but the tool should certainly allow you to accept pre-release versions by providing the appropriate option.

1 Like

Pre-releases are excluded by default from any range and need to be opted into by having one of the bounds be a pre-release version. So e.g. 510.0.1 ..< 601.0.0-pre would include 600.0.0-prerelease-2024-05-28.

This is done to avoid any accidental inclusion of pre-releases.

I think it would be pretty reasonable to allow root packages to opt-in any dependencies into accepting pre-releases, so I'd agree that conceptually, your case should be made to work.

1 Like

the goal is to use swift-testing in a project that also has a dependency on a package that uses macros. is swift-testing simply incompatible with macros?

Oh, are you saying you're getting into this situation because of the dependency on 600.0.0-latest of swift-syntax in swift-testing? That seems... unexpected at least. I assumed you were somehow forcing a pre-release in your root package (e.g. by using .exact).

yes, i was trying to debug the issue by adding an explicit SwiftSyntax dependency, which is why it shows up as a root package dependency

Hm, do you have an example package which fails? Depending on swift-dom and swift-testing seems to work for me (with main-ish SwiftPM):

~/Desktop/test
❯ rg '\.package' Package.swift 
9:        .package(url: "git@github.com:tayloraswift/swift-dom.git", branch: "master"),
10:        .package(url: "https://github.com/apple/swift-testing", branch: "main"),

~/Desktop/test
❯ cat Package.resolved|jq '.pins.[] | {identity,state}'
{
  "identity": "swift-dom",
  "state": {
    "branch": "master",
    "revision": "c54da6ef6c10fc54651609fe8233221d5e1f35fe"
  }
}
{
  "identity": "swift-syntax",
  "state": {
    "revision": "74c759fe021b87849501af3808ef24fcba8dfff3",
    "version": "600.0.0-prerelease-2024-06-04"
  }
}
{
  "identity": "swift-testing",
  "state": {
    "branch": "main",
    "revision": "6b948b90417be5d63a164f525fefa75bcc9fd700"
  }
}

you are right, this was specifically triggered by pinning SwiftSyntax to a prerelease version in root package. this also happens when pinning SwiftSyntax to the normal release version, as would be done if the package has macros, but this is less surprising as swift-testing explicitly requires a prerelease version of SwiftSyntax.

that gave me the idea to try a range version where one of the bounds is a pre-release version:

.package(url: "https://github.com/apple/swift-syntax", 
    "510.0.1" ..< "601.0.0-pre"),

but then there is an internal error:

error: InternalError(description: "Internal error. Please file a bug at https://github.com/apple/swift-package-manager/issues with this info. Expected root cause {swift-dom[everything] 1.0.1, ¬swift-syntax[everything] 510.0.1..<601.0.0} to almost satisfy the current partial solution:\n * [Decision 0: dependency-test[everything] 1.0.0]\n * [Derivation: swift-syntax[everything] 510.0.1..<601.0.0-pre ← {dependency-test[everything] 1.0.0, ¬swift-syntax[everything] 510.0.1..<601.0.0-pre}]\n * [Derivation: swift-testing[everything] 0.9.0..<0.10.0 ← {dependency-test[everything] 1.0.0, ¬swift-testing[everything] 0.9.0..<0.10.0}]\n * [Derivation: swift-system[everything] 1.3.0..<2.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-system[everything] 1.3.0..<2.0.0}]\n * [Derivation: swift-markdown[everything] 0.3.0..<0.4.0 ← {dependency-test[everything] 1.0.0, ¬swift-markdown[everything] 0.3.0..<0.4.0}]\n * [Derivation: swift-nio-http2[everything] 1.31.0..<2.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-nio-http2[everything] 1.31.0..<2.0.0}]\n * [Derivation: swift-nio-ssl[everything] 2.26.0..<3.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-nio-ssl[everything] 2.26.0..<3.0.0}]\n * [Derivation: swift-nio[everything] 2.65.0..<3.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-nio[everything] 2.65.0..<3.0.0}]\n * [Derivation: swift-collections[everything] 1.1.0..<2.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-collections[everything] 1.1.0..<2.0.0}]\n * [Derivation: swift-atomics[everything] 1.2.0..<2.0.0 ← {dependency-test[everything] 1.0.0, ¬swift-atomics[everything] 1.2.0..<2.0.0}]\n * [Derivation: swift-png[everything] 4.4.3..<4.5.0 ← {dependency-test[everything] 1.0.0, ¬swift-png[everything] 4.4.3..<4.5.0}]\n * [Derivation: swift-json[everything] 1.1.0..<1.2.0 ← {dependency-test[everything] 1.0.0, ¬swift-json[everything] 1.1.0..<1.2.0}]\n * [Derivation: swift-mongodb[everything] 0.18.1..<0.19.0 ← {dependency-test[everything] 1.0.0, ¬swift-mongodb[everything] 0.18.1..<0.19.0}]\n * [Derivation: swift-hash[everything] 0.6.0..<0.7.0 ← {dependency-test[everything] 1.0.0, ¬swift-hash[everything] 0.6.0..<0.7.0}]\n * [Derivation: swift-grammar[everything] 0.4.0..<0.5.0 ← {dependency-test[everything] 1.0.0, ¬swift-grammar[everything] 0.4.0..<0.5.0}]\n * [Derivation: swift-dom[everything] 1.0.1..<1.1.0 ← {dependency-test[everything] 1.0.0, ¬swift-dom[everything] 1.0.1..<1.1.0}]\n * [Derivation: ¬swift-dom[everything] 1.0.2..<1.1.0 ← {swift-dom[everything] 1.0.2..<1.1.0}]\n")

here is a manifest that causes the error:

// swift-tools-version: 5.10

import PackageDescription

let package = Package(
    name: "dependency-test",
    products: [],
    dependencies: [
        .package(url: "https://github.com/tayloraswift/swift-dom", .upToNextMinor(from: "1.0.1")),
        .package(url: "https://github.com/apple/swift-testing", .upToNextMinor(from: "0.9.0")),
        .package(url: "https://github.com/apple/swift-syntax", "510.0.1" ..< "601.0.0-pre"),
    ],
    targets: []
)

and the error for the reduced case

error: InternalError(description: "Internal error. Please file a bug at https://github.com/apple/swift-package-manager/issues with this info. Expected root cause {swift-dom[everything] 1.0.1, ¬swift-syntax[everything] 510.0.1..<601.0.0} to almost satisfy the current partial solution:\n * [Decision 0: dependency-test[everything] 1.0.0]\n * [Derivation: swift-syntax[everything] 510.0.1..<601.0.0-pre ← {dependency-test[everything] 1.0.0, ¬swift-syntax[everything] 510.0.1..<601.0.0-pre}]\n * [Derivation: swift-testing[everything] 0.9.0..<0.10.0 ← {dependency-test[everything] 1.0.0, ¬swift-testing[everything] 0.9.0..<0.10.0}]\n * [Derivation: swift-dom[everything] 1.0.1..<1.1.0 ← {dependency-test[everything] 1.0.0, ¬swift-dom[everything] 1.0.1..<1.1.0}]\n * [Derivation: ¬swift-dom[everything] 1.0.2..<1.1.0 ← {swift-dom[everything] 1.0.2..<1.1.0}]\n")

i also filed the issue here: InternalError: Expected root cause · Issue #7643 · apple/swift-package-manager · GitHub

1 Like

Maybe your Package.swift falls into cornercase of a "unversioned" dependency?