astral-sh/uv · error · anyhow::Error

The file `{}` appears to be a TOML file, but constraints mus

Error message

The file `{}` appears to be a TOML file, but constraints must be specified in `requirements.txt` format

What it means

Thrown by RequirementsSource::from_constraints_txt (crates/uv-requirements/src/sources.rs:143) when the constraints path has a .toml extension (case-insensitive) but its name is not one of the specially-handled files (pyproject.toml/setup.py/setup.cfg are caught earlier, pylock by error 40). uv only parses constraints in requirements.txt format, so any other TOML file is rejected before parsing.

Source

Thrown at crates/uv-requirements/src/sources.rs:143

                    path.user_display(),
                    file_name
                ));
            }
        }
        if path
            .file_name()
            .and_then(OsStr::to_str)
            .is_some_and(is_pylock_toml)
        {
            return Err(anyhow::anyhow!(
                "The file `{}` appears to be a `pylock.toml` file, but constraints must be specified in `requirements.txt` format",
                path.user_display(),
            ));
        } else if path
            .extension()
            .is_some_and(|ext| ext.eq_ignore_ascii_case("toml"))
        {
            return Err(anyhow::anyhow!(
                "The file `{}` appears to be a TOML file, but constraints must be specified in `requirements.txt` format",
                path.user_display(),
            ));
        }
        Ok(Self::RequirementsTxt(path))
    }

    /// Parse a [`RequirementsSource`] from an `overrides.txt` file.
    pub fn from_overrides_txt(path: PathBuf) -> Result<Self> {
        if path == Path::new("-") {
            return Ok(Self::Extensionless(path));
        }

        for file_name in ["pyproject.toml", "setup.py", "setup.cfg"] {
            if path.ends_with(file_name) {
                return Err(anyhow::anyhow!(
                    "The file `{}` appears to be a `{}` file, but overrides must be specified in `requirements.txt` format",
                    path.user_display(),

View on GitHub (pinned to f1a42680ff)

Solutions

  1. Convert the TOML to a flat requirements.txt-format file (`flask>=1.0` per line) and pass that to --constraints
  2. If the TOML is a pyproject.toml you want to constrain by, extract the dependency lists into a .txt file (e.g. `uv export -o constraints.txt` from that project)
  3. Check for a typo in the constraints path — the intended constraints.txt may have been misnamed

Example fix

# before
uv pip install --constraints deps.toml flask
# after
# deps.txt: each line like `flask>=1.0`
uv pip install --constraints deps.txt flask
Defensive patterns

Strategy: validation

Validate before calling

fn acceptable_constraint_path(path: &Path) -> bool {
    path == Path::new("-")
        || path
            .extension()
            .map(|ext| !ext.eq_ignore_ascii_case("toml"))
            .unwrap_or(true)
}

if !acceptable_constraint_path(&path) {
    // convert to requirements.txt format before passing to uv
}

Try / catch

match RequirementsSource::from_constraints_txt(path) {
    Err(err) if err.to_string().contains("TOML file") => {
        eprintln!("constraints must be requirements.txt format; got {path:?}");
        continue;
    }
    source => source?,
}

Prevention

When it happens

Trigger: Running `uv pip install --constraints Cargo.toml`, `uv pip install --constraints deps.toml`, or `--constraints CONSTRAINTS.TOML`; any call to from_constraints_txt with a path whose extension equals toml ignoring case.

Common situations: Users keep dependency pins in a custom TOML file and assume uv reads arbitrary TOML; copy-pasting a `--constraint pyproject.toml` invocation from another tool's docs; configuration management tools generating .toml constraint artifacts.

Related errors


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