astral-sh/uv · error
Multiple index URLs specified: `{existing}` vs. `{index_url}
Error message
Multiple index URLs specified: `{existing}` vs. `{index_url}` What it means
Thrown during RequirementsSpecification merging of plain requirements sources: if the accumulated spec already has an index_url and a new source also defines one whose CanonicalUrl differs, uv refuses to continue. CanonicalUrl comparison ignores trivial URL differences (trailing slashes, default ports), so this only fires for genuinely different indexes.
Source
Thrown at crates/uv-requirements/src/specification.rs:583
"Multiple `pylock.toml` files specified: `{}` vs. `{}`",
existing.user_display(),
pylock.user_display()
));
}
spec.pylock = Some(pylock);
}
// Use the first project name discovered.
if spec.project.is_none() {
spec.project = source.project;
}
if let Some(index_url) = source.index_url {
if let Some(existing) = spec.index_url
&& CanonicalUrl::new(index_url.url().clone())
!= CanonicalUrl::new(existing.url().clone())
{
return Err(anyhow::anyhow!(
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
));
}
spec.index_url = Some(index_url);
}
spec.no_index |= source.no_index;
spec.extra_index_urls.extend(source.extra_index_urls);
spec.find_links.extend(source.find_links);
spec.no_binary.extend(source.no_binary);
spec.no_build.extend(source.no_build);
spec.require_hashes |= source.require_hashes;
}
// Read all constraints, treating both requirements _and_ constraints as constraints.
// Overrides are ignored.
for source in constraints {
let source = Self::from_source_with_cache(source, client_builder, &mut cache).await?;
for entry in source.requirements {View on GitHub (pinned to f1a42680ff)
Solutions
- Pick one canonical index: delete the `--index-url` line from the requirements file or drop the CLI/config flag, so only one remains.
- If you need multiple indexes, move the secondary one to `--extra-index-url` / `[[index]]` entries, which are allowed to accumulate.
- Verify the two URLs really are the same index after redirects; if they are, make the strings identical (or canonicalize trailing slash) so CanonicalUrl comparison passes.
Example fix
# before (reqs.txt has: --index-url https://pypi.org/simple) uv pip compile --index-url https://mirror.internal/simple -r reqs.txt # after uv pip compile --extra-index-url https://mirror.internal/simple -r reqs.txt
Defensive patterns
Strategy: validation
Validate before calling
# Rust: canonicalize and compare index URLs before merging requirement sources
use uv_distribution_types::CanonicalUrl;
fn assert_single_index(urls: Vec<Option<IndexUrl>>) -> anyhow::Result<Option<IndexUrl>> {
let mut acc: Option<IndexUrl> = None;
for url in urls.into_iter().flatten() {
if let Some(existing) = &acc {
if CanonicalUrl::new(url.url().clone()) != CanonicalUrl::new(existing.url().clone()) {
anyhow::bail!("index conflict: {existing} vs {url}");
}
} else {
acc = Some(url);
}
}
Ok(acc)
} Prevention
- Declare the primary index in exactly one layer (CLI, config, or file) and use --extra-index-url for the rest.
- Grep requirements/constraint files for `--index-url` lines before feeding them alongside CLI index flags.
- Remember trailing slashes and default ports are normalized away; real differences in host/path are what trigger this.
When it happens
Trigger: Combining `--index-url` on the CLI with a requirements.txt containing its own `--index-url` line pointing elsewhere; concatenating two requirements files each declaring a different `--index-url`; feeding `-r a.txt -r b.txt` where both pin incompatible indexes.
Common situations: A private mirror index configured globally (uv.toml or env) colliding with an index pinned inside a vendored requirements file; copy-pasting requirements files between projects that target different internal mirrors; a lock/requirements export that embeds `--index-url` while the user also passes one explicitly.
Related errors
- Multiple `pylock.toml` files specified: `{}` vs. `{}`
- pip-compile's `--config` is unsupported (uv does not use a c
- pip-compile's `--emit-options` is unsupported (try `--emit-b
- pip-sync's `--config` is unsupported (uv does not use a conf
- Cannot specify additional requirements alongside a `pylock.t
AI-assisted analysis of astral-sh/uv@f1a42680ff (2026-08-16).
Data as JSON: /api/errors/265e25e883b7135a.
Report an issue: GitHub.