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

  1. Pick one canonical index: delete the `--index-url` line from the requirements file or drop the CLI/config flag, so only one remains.
  2. If you need multiple indexes, move the secondary one to `--extra-index-url` / `[[index]]` entries, which are allowed to accumulate.
  3. 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

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


AI-assisted analysis of astral-sh/uv@f1a42680ff (2026-08-16). Data as JSON: /api/errors/265e25e883b7135a. Report an issue: GitHub.