jdx/mise · error
Python locks require credential-free HTTP artifact URLs…
Error message
Python locks require credential-free HTTP artifact URLs; configure authentication outside the lockfile
What it means
validate_portable_urls enforces that every artifact URL recorded in a generated Python (uv) lockfile is an http/https URL with no embedded credentials (username/password) and no query string. Portable locks must work across machines, so credentials cannot be baked into the lockfile; this error signals a URL that would leak or bind authentication into the lock.
Solutions
- Remove credentials and query strings from the artifact URLs and configure authentication out-of-band (netrc, keyring, or env-based index auth)
- Use a credential-free internal mirror/proxy URL for private artifacts
- Regenerate the lock against an index that serves plain https URLs
Example fix
# before (lockfile entry) url = "https://user:token@pypi.example.com/pkg.whl" # after url = "https://pypi.example.com/pkg.whl" # auth via netrc/env
Defensive patterns
Strategy: validation
Validate before calling
// validate a lockfile artifact URL before use const u = new URL(url); const ok = (u.protocol === 'https:' || u.protocol === 'http:') && !u.username && !u.password && u.search === '';
Prevention
- Never embed user:pass@ or token query params in lockfile URLs
- Configure private index auth via netrc/keyring/env instead of URLs
- Use a credential-free internal mirror for private packages
When it happens
Trigger: Validating a uv lock (validate_uv_lock) or a lock entry's URL when the artifact URL contains userinfo (user:pass@), a password, or a query parameter, or uses a non-http(s) scheme.
Common situations: Pointing the lock at a private package index whose artifact URLs embed basic-auth credentials; using a mirror that appends tokens as query strings; hand-editing a lockfile with a credentialed internal registry URL.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- GitHub Actions OIDC request URL must use HTTPS
- invalid Python entry point name
- lockfile generation would change the recorded signer…
- lockfile generation would downgrade additional artifact…
- lockfile generation would downgrade recorded provenance…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/01a34eaafa0743ee.
Report an issue: GitHub.
Appendix: source
Thrown at src/backend/pipx/lock.rs:635
{
url.set_path("/simple/");
} else {
let path = url.path().trim_end_matches('/').trim_end_matches("/simple");
url.set_path(&format!("{path}/simple/"));
}
Ok(url.into())
}
fn validate_portable_urls(value: &toml::Value) -> Result<()> {
match value {
toml::Value::String(s) if s.contains("://") => {
let url = url::Url::parse(s)?;
if !matches!(url.scheme(), "https" | "http")
|| !url.username().is_empty()
|| url.password().is_some()
|| url.query().is_some()
{
bail!(
"Python locks require credential-free HTTP artifact URLs; configure authentication outside the lockfile"
);
}
}
toml::Value::Table(t) => {
for value in t.values() {
validate_portable_urls(value)?;
}
}
toml::Value::Array(a) => {
for value in a {
validate_portable_urls(value)?;
}
}
_ => (),
}
Ok(())
}View on GitHub (pinned to 533346cc37)