uv: uv pip install resulting in 401 Unauthorized with private index url

I am trying to use uv pip install with a private repository, and I am getting (401 Unauthorized errors). The same URL works completely fine with native pip, i.e. if I just remove the “uv”.

I cannot share the real URL, but there might be characters which might be raising some issues (like ‘@’), so here is a pseudo-example:

uv pip install privatepackage --index-url https://not_real@fake.com:fake_key@fake.aa.bb/path1/path2/path3/path4/path5

My current uv version is 0.1.5, and the Python env is 3.8.

About this issue

  • Original URL
  • State: closed
  • Created 4 months ago
  • Comments: 33 (13 by maintainers)

Commits related to this issue

Most upvoted comments

@zanieb Here a standalone setup to reproduce with simple PEP 503 index and Basic Authentication.

In some folder create,

index.html

<!DOCTYPE html>
<html>
  <body>
    <a href="/non-existing-package/">non-existing-package</a>
  </body>
</html>

/non-existing-package/index.html

<html><head>
    <meta name="pypi:repository-version" content="1.1">
  </head>
  <body>
    <h1>Links for non-existing-package</h1>
<a href="http://127.0.0.1:8080/non-existing-package/non-existing-package-0.1.0.tar.gz#sha256=fb1aa1f8d35a2e3b7bbc2ce632ece9571bb8093dec79826a54be075f15b11ecd">non-existing-package-0.1.0.tar.gz</a><br>

</body></html>

and create this fake package with

touch /non-existing-package/non-existing-package-0.1.0.tar.gz

then run with node,

npx http-server --username user --password password

to get a server with basic auth.

Running uv,

uv pip install non-existing-package==0.1.0 --extra-index-url http://user:password@127.0.0.1:8080/ --refresh -v

fails with,

error: Failed to download and build: non-existing-package==0.1.0
  Caused by: HTTP status client error (401 Unauthorized) for url (http://127.0.0.1:8080/non-existing-package/non-existing-package-0.1.0.tar.gz#sha256=fb1aa1f8d35a2e3b7bbc2ce632ece9571bb8093dec79826a54be075f15b11ecd)

So the problem is that this simple API returns absolute URLs for package versions, and the access token is no longer part of the URL hence the 401 error. It works if the URLs are relative.

I’m not sure for other hosting services but Gitlab packages, does return such absolute URLs and consequently fail.

Unless I’m mistaken, the corresponding logic in pip is here https://github.com/pypa/pip/blob/b647ed5782e1fc5627e5e18a036130fea0b413e6/src/pip/_internal/network/auth.py#L404 to account for the fact that the package URL for a private index may not contain credentials.

Thanks for fixing it so fast ! Nice to see this projet moving forward as swiftly as it does !

These are some high-quality comments, thanks @rth.

I have the same problem. I’m using a jfrog repo. The index url looks like:

https://$USERNAME:$TOKEN@xxx.jfrog.io/yyy/zzz

I confirm #1902 fixes the issue for JFrog!

Thanks for the (extremely quick!!!) response! I’m sorry, but I can’t share more details about the private index.

If it might be helpful, I explicitly mentioned the @ character because some of our developers had problems in the past due to ‘@’ being converted into ‘%40’ at some point depending on the setup, and I see this happening during the uv_client::html::parse stage in verbose mode.

After having installed uv 0.1.9, I still have a 403 Forbidden issue when trying to uv pip install a package hosted on a private artifactory repository.

[EDIT] My bad, https://github.com/astral-sh/uv/pull/1902 is not part of uv 0.1.9, waiting for the next release 😇

I just checked out #1902 and I can confirm it now works for GitLab for me

fingers crossed! FWIW same issue on gitlab pypi registry (at uv 0.1.9, after cleaning the cache).

We’ve identified this as a problem preserving authorization headers in streamed range requests.

https://github.com/astral-sh/uv/pull/1902 should resolve this.

Trial JFrog account here I come