2025, Oct 20 20:00
Prevent uv from resolving the wrong PyTorch CUDA build: use environment markers for x86_64 vs aarch64
Learn how to stop uv from pulling torch==2.6.0+cu124 on aarch64. Use environment markers to target PyTorch CUDA 12.4 on x86_64 and CUDA 12.8 on aarch64
Targeting multiple CUDA variants across architectures often looks trivial until your resolver disagrees. A common case is Linux x86_64 that must stay on CUDA 12.4, while aarch64 uses CUDA 12.8. PyTorch doesn’t ship CUDA 12.4 wheels for arm64, so a resolver must be steered away from attempting that combo in the first place.
Reproducing the issue
The setup below relies on extras and required-environments to guide uv toward the right CUDA build depending on the platform. Despite that, uv still tries to resolve the CUDA 12.4 wheel for aarch64 and fails.
[project]
name = "uv_extras_case"
version = "0.1.1"
description = ""
readme = "README.md"
requires-python = ">=3.13"
dependencies = []
[tool.uv]
conflicts = [
    [{extra="cu128"}, {extra="cu124"}]
]
required-environments = [
    "sys_platform == 'linux' and platform_machine == 'x86_64'  and extra == 'cu124'",
    "sys_platform == 'linux' and platform_machine == 'aarch64' and extra == 'cu128'",
]
index-strategy = "unsafe-best-match"
[project.optional-dependencies]
cu124 = [
    "torch==2.6.0+cu124",
]
cu128 = [
    "torch==2.7.0+cu128",
]
[[tool.uv.index]]
name = "pt-cu128"
url = "https://download.pytorch.org/whl/cu128"
[[tool.uv.index]]
name = "pt-cu124"
url = "https://download.pytorch.org/whl/cu124"
What actually goes wrong
The resolver proceeds as if the extra in required-environments doesn’t prevent it from exploring incompatible combinations. The failure shows up as an unsatisfiable set of constraints for aarch64 when uv attempts to pull torch==2.6.0+cu124, which simply doesn’t have wheels for that platform.
No solution found … Because torch==2.6.0+cu124 has no … aarch64 … compatible wheels … we can conclude that … requirements are unsatisfiable.
In other words, limiting extras via required-environments isn’t enough to block uv from considering torch+cu124 on arm.
The fix
Make the platform constraint part of the dependency itself using an environment marker. This tells uv unambiguously that torch+cu124 is installable only on Linux x86_64, and therefore should never be attempted on aarch64.
[project.optional-dependencies]
cu124 = [
    "torch==2.6.0+cu124; sys_platform == 'linux' and platform_machine == 'x86_64'",
]
cu128 = [
    "torch==2.7.0+cu128",
]
With this in place, uv won’t try to resolve torch+cu124 on arm64, and the resolution for aarch64 proceeds with the CUDA 12.8 build as intended.
Why this matters
Cross-architecture environments regularly combine different dependency graphs and indexes. If a package isn’t published for a specific platform-accelerator pair, letting the resolver discover that by trial is expensive and brittle. Encoding the platform restriction right on the dependency line avoids unsatisfiable resolutions and keeps your environment definitions self-documenting.
Takeaways
When a package is platform-specific, express that constraint directly on the dependency using environment markers. Relying on extras and high-level environment selection alone may still leave room for the resolver to explore invalid combinations, as seen with torch+cu124 on aarch64. A small, explicit marker eliminates the ambiguity and leads the resolver to a clean solution.