{"record":{"id":"6d6afad73df231dd","repo":"astral-sh/uv","slug":"unnamed-requirements-are-not-allowed-as-constraint","errorCode":null,"errorMessage":"Unnamed requirements are not allowed as constraints (found: `{requirement}`)","messagePattern":"Unnamed requirements are not allowed as constraints \\(found: `(.+?)`\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/uv-requirements/src/specification.rs","lineNumber":610,"sourceCode":"            spec.no_binary.extend(source.no_binary);\n            spec.no_build.extend(source.no_build);\n            spec.require_hashes |= source.require_hashes;\n        }\n\n        // Read all constraints, treating both requirements _and_ constraints as constraints.\n        // Overrides are ignored.\n        for source in constraints {\n            let source = Self::from_source_with_cache(source, client_builder, &mut cache).await?;\n            for entry in source.requirements {\n                match entry.requirement {\n                    UnresolvedRequirement::Named(requirement) => {\n                        spec.constraints.push(NameRequirementSpecification {\n                            requirement,\n                            hashes: entry.hashes,\n                        });\n                    }\n                    UnresolvedRequirement::Unnamed(requirement) => {\n                        return Err(anyhow::anyhow!(\n                            \"Unnamed requirements are not allowed as constraints (found: `{requirement}`)\"\n                        ));\n                    }\n                }\n            }\n            spec.constraints.extend(source.constraints);\n\n            if let Some(index_url) = source.index_url {\n                if let Some(existing) = spec.index_url\n                    && CanonicalUrl::new(index_url.url().clone())\n                        != CanonicalUrl::new(existing.url().clone())\n                {\n                    return Err(anyhow::anyhow!(\n                        \"Multiple index URLs specified: `{existing}` vs. `{index_url}`\",\n                    ));\n                }\n                spec.index_url = Some(index_url);\n            }","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/astral-sh/uv/blob/f1a42680ff5272232d65748acf338b19778dde24/crates/uv-requirements/src/specification.rs#L592-L628","documentation":"Constraints in uv must be named requirements (e.g., `flask<2`), because a constraint only pins versions of an already-requested package. When a constraint source is parsed and an UnresolvedRequirement::Unnamed (a direct URL or file path requirement) is found, uv rejects it immediately during merging.","triggerScenarios":"Running `uv pip compile -c constraints.txt` (or `uv lock` with a constraints file) where constraints.txt contains a line like `./libs/my-pkg.tar.gz`, `https://example.com/pkg.whl`, or a VCS URL; passing a URL requirement via `--constraint` directly.","commonSituations":"Reusing a full requirements.txt as a constraints file without pruning its URL entries; CI that generates constraints from a lock export that includes direct-URL dependencies; teams copy-pasting a private-package URL into the constraints file.","solutions":["Remove the unnamed (URL/path) entry named in the error from the constraints file — constraints cannot pin direct-URL packages.","If the direct-URL package must be pinned, move it to the main requirements source (it is already fully specified there) and constrain only named packages in the constraints file.","If you want the exact version of a local package, declare it in the requirements with its path and use constraints only for its transitive named dependencies."],"exampleFix":"# before (constraints.txt)\nnumpy==1.26.4\n./wheels/team-util-1.0-py3-none-any.whl\n# after (constraints.txt)\nnumpy==1.26.4\n# direct URL moved to requirements.txt instead","handlingStrategy":"validation","validationCode":"# Rust: reject unnamed requirements before passing a file as constraints\nuse uv_requirements::UnresolvedRequirement;\n\nfn validate_constraints(reqs: &[RequirementEntry]) -> anyhow::Result<()> {\n    for entry in reqs {\n        if let UnresolvedRequirement::Unnamed(ref r) = entry.requirement {\n            anyhow::bail!(\"unnamed requirement not allowed as constraint: {r}\");\n        }\n    }\n    Ok(())\n}","typeGuard":"fn is_named_constraint(entry: &RequirementEntry) -> bool {\n    matches!(entry.requirement, UnresolvedRequirement::Named(_))\n}","tryCatchPattern":null,"preventionTips":["Keep constraints files to `name<op>version` lines only — no URLs, paths, or VCS specs.","Never reuse a full requirements.txt as a constraints file without pruning direct-URL entries.","In CI, lint constraint files for lines that don't start with a package name."],"tags":["constraints","requirements","validation"],"backgroundTag":null,"analyzedSha":"f1a42680ff5272232d65748acf338b19778dde24","analyzedAt":"2026-08-16T04:51:47.599Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}