Skip to content

Improve the 403 forbidden hint to suggest ignore-error-codes when applicable#19521

Merged
zanieb merged 1 commit into
mainfrom
zb/hint-403
May 26, 2026
Merged

Improve the 403 forbidden hint to suggest ignore-error-codes when applicable#19521
zanieb merged 1 commit into
mainfrom
zb/hint-403

Conversation

@zanieb
Copy link
Copy Markdown
Member

@zanieb zanieb commented May 21, 2026

No description provided.

@zanieb zanieb added the error messages Messaging when something goes wrong label May 21, 2026
@zanieb zanieb marked this pull request as ready for review May 21, 2026 19:52
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented May 21, 2026

uv test inventory changes

This PR changes the tests when compared with the latest main baseline.

  • Added tests: 1
  • Removed tests: 0
  • Changed suites: 1
uv::it: +1 / -0

Added:

  • uv::it::edit::lock_forbidden_index_with_available_package

Removed: none

@zanieb zanieb requested a review from charliermarsh May 21, 2026 20:19
@zanieb
Copy link
Copy Markdown
Member Author

zanieb commented May 22, 2026

See #19517

Copy link
Copy Markdown
Contributor

@Gankra Gankra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits and queries but this looks like an improvement.

Comment on lines +744 to +745
/// Return the prior successful Simple API access for an index that returned `403 Forbidden`.
pub fn forbidden_access(&self, index_url: &IndexUrl) -> Option<ForbiddenIndexAccess> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function name and description are really confusing for the actual behaviour here.

I would maybe call this forbidden_access_hint or forbidden_access_pattern. Like, what this is doing is looking at the successful and failed requests and noting whether the failures and successes are disjoint sets, because if they are that indicates all the failures are due to missing packages and we can recommend config to enable fallback.

Comment on lines +755 to +757
.any(|package_name| capabilities.successful_simple_api.contains(package_name))
{
return Some(ForbiddenIndexAccess::SamePackage);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels weird this is just looking at all queries and that we're not taking a specific package as input.

It also feels weird that if we get a single matching hit we go "well the user doesn't need this suggestion anymore".

Is there any rationale to either of these choices? I'm fine with landing it as a strict improvement either way.

Comment on lines -640 to -642
/// We only store indexes that lack capabilities (i.e., don't support range requests, aren't
/// authorized). The benefit is that the map is almost always empty, so validating capabilities is
/// extremely cheap.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we worried about the cost here? This will add a lot of contention, right? Literally every request has to mutate this now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm yes that does seem problematic, thanks for pointing that out.

I feel like we should avoid that somehow.

Comment on lines +727 to +733
self.0
.write()
.unwrap()
.entry(index_url)
.or_default()
.successful_simple_api
.insert(package_name);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One possible not-even-sure-it's-an-optimization we could do here since we do have a RWLock: we could first acquire read-only and check if the package name already appears, and early-return if it does.

Comment thread crates/uv/tests/it/edit.rs Outdated
╰─▶ Because idna was not found in the package registry and anyio==4.3.0 depends on idna>=2.8, we can conclude that anyio==4.3.0 cannot be used.
And because only anyio==4.3.0 is available and your project depends on anyio, we can conclude that your project's requirements are unsatisfiable.

hint: An index URL (http://[LOCALHOST]/) returned a 403 Forbidden error, but uv received a successful response for another package from the index. If the failing package is not present on this index, consider adding `ignore-error-codes = [403]` to the index's `[[tool.uv.index]]` entry to continue searching across indexes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm, that's nice.

@charliermarsh
Copy link
Copy Markdown
Member

I'll defer to @Gankra on the review, I like the hint though.

Comment thread crates/uv-resolver/src/pubgrub/report.rs Outdated
Comment thread crates/uv-resolver/src/pubgrub/report.rs Outdated
Comment thread crates/uv-resolver/src/pubgrub/report.rs Outdated
@zanieb zanieb merged commit aac683c into main May 26, 2026
57 checks passed
@zanieb zanieb deleted the zb/hint-403 branch May 26, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

error messages Messaging when something goes wrong

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants