astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
19.94k stars 591 forks source link

`uv pip compile` possibly generating an unsatisfiable requirements file #6038

Open thecityofguanyu opened 1 month ago

thecityofguanyu commented 1 month ago

Overview

I'm not sure how this is possible?

See below for the relevant snippet from unsatisfiable lockfile that was emitted.

# This file was autogenerated by uv via the following command:
#    uv pip compile --no-emit-find-links --no-emit-index-url --no-emit-trusted-host --strip-extras --unsafe-package=pip --output-file=etc/pythondeps.linux.txt etc/pythondeps.linux.in
...
boto3==1.34.153
    # via
    #   -c etc/constraints.txt
    #   -r etc/pythondeps.lst
    #   redacted-lib-name
boto3-stubs==1.34.149
    # via -r etc/pythondeps.lst
botocore==1.34.149
    # via
    #   boto3
    #   s3transfer
botocore-stubs==1.34.153
    # via boto3-stubs
...
s3transfer==0.10.2
    # via boto3

We version the lockfile, so it is interesting to note that uv was actually downgrading those versions to 1.34.149 for some reason? (relative to what we already had checked in, which was 1.34.153 across the board)

image


Relevant lines from the constraints.txt file referenced in the above:

boto3 >= 1.28.58

Relevant lines from the pythondeps.lst file referenced in the above:

boto3
boto3-stubs[s3]
redacted-lib-name

Error observed when trying to consume the generated lockfile:

[2024-08-11T21:52:33.685Z] Successfully installed pip-24.2 uv-0.2.33
[2024-08-11T21:52:34.252Z] uv 0.2.33
[2024-08-11T21:52:40.824Z]   × No solution found when resolving dependencies:
[2024-08-11T21:52:40.824Z]   ╰─▶ Because boto3==1.34.153 depends on botocore>=1.34.153,<1.35.0
[2024-08-11T21:52:40.824Z]       and you require boto3==1.34.153, we can conclude that you require
[2024-08-11T21:52:40.824Z]       botocore>=1.34.153,<1.35.0.
[2024-08-11T21:52:40.824Z]       And because you require botocore==1.34.149, we can conclude that the
[2024-08-11T21:52:40.824Z]       requirements are unsatisfiable.

Other information

zanieb commented 1 month ago

Thanks for the thorough report. Does this occur on the latest version? There's been a lot of resolver work in the last few weeks.

thecityofguanyu commented 1 month ago

I can't say with for sure which uv version this occurred on due to lack of logs from this dev's local execution. We do usually live-at-head with uv, so if I compare to the CI run that failed from their commit, then I'd say it was likely to be 0.2.33.

My understanding our org syncs our PyPI mirror weekly, so 0.2.33 happens to still be the latest available to us at this time.

We also haven't seen this happen apart from the one time.

thecityofguanyu commented 1 month ago

Additional context not mentioned earlier: Python 3.8

charliermarsh commented 1 month ago

I'd love to figure this one out... Will be really hard without a repro though. I'm trying with cargo run pip compile req.txt -c constraints.txt -o output.txt -n --exclude-newer 2024-08-11T21:52:33.685Z -p 3.8 using the example pinned versions above but not reproducing yet.

thecityofguanyu commented 1 month ago

Using the examples above, I gave it a shot with some repetitions yesterday and wasn't able to reproduce it.

By all accounts, we've only seen it happen this one time. I considered chalking this up to operator error and not opening an issue here, but I couldn't reason myself into an explanation that might explain the symptoms.

More context on the (non-minimal) execution that triggered this (one time):

I'll see if I can try more repetitions again with the full requirements/constraints -- not trimmed down to the problematic packages.

charliermarsh commented 1 month ago

Yeah I also can't come up with a great explanation for how it could happen. The only things I could imagine are...

thecityofguanyu commented 1 month ago

You have an --override defined somewhere, that's overriding the dependencies (seems unlikely, but it could lead to this kind of behavior).

Definitely no --override defined.

There's some kind of caching error in the index such that the wrong requirements were reported

Maybe, although I don't think I'll be able to corroborate that with logs.


Still haven't reproduced it. The uv pip compile correctly fails when you explicitly constrain in a way to force the versions that were shown in the bad lockfile.

DEBUG Prepared metadata for: redacted-lib-name ==0.1.24
  × No solution found when resolving dependencies:
  ╰─▶ Because boto3==1.34.153 depends on botocore>=1.34.153,<1.35.0 and botocore<=1.34.149, we can conclude that boto3==1.34.153 cannot be used.
      And because only the following versions of boto3 are available:
          boto3<=1.34.153
          boto3==1.34.154
          boto3==1.34.155
      we can conclude that boto3>=1.34.153,<1.34.154 cannot be used. (1)

      Because boto3==1.34.154 depends on botocore>=1.34.154,<1.35.0 and botocore<=1.34.149, we can conclude that boto3==1.34.154 cannot be used.
      And because we know from (1) that boto3>=1.34.153,<1.34.154 cannot be used, we can conclude that boto3>=1.34.153,<1.34.155 cannot be used. (2)

      Because boto3==1.34.155 depends on botocore>=1.34.155,<1.35.0 and botocore<=1.34.149, we can conclude that boto3==1.34.155 cannot be used.
      And because we know from (2) that boto3>=1.34.153,<1.34.155 cannot be used, we can conclude that boto3>=1.34.153 cannot be used.
      And because you require boto3>=1.34.153, we can conclude that the requirements are unsatisfiable.

There was a working theory that maybe the user had git add -p to commit only some of the lockfile changes. I thought that made sense at first.

If you notice from the diff where the bad lockfile is introduced, you'll see that there's also a metadata change of # via -r pythondeps.lst to # via -r etc/pythondeps.lst. This is due to a working directory differences between our local Makefile and the CI process that also pushes new lockfiles.

That little comment change is there for every package in the lockfile, so a partial add theory would mean that somehow every change except those versions made it into the commit. This makes it seem less likely to me.

charliermarsh commented 1 month ago

You could consider running in --verbose on CI, and then seeing if it pops up again so we can get more extensive logs.

thecityofguanyu commented 1 month ago

Sure! We're grasping at straws now, so it can't hurt to log more verbosely just in case.

With that said, I wouldn't be hopeful from that approach. We pip-compile in CI once per week, and the one-off failure was from a local execution. 😕