Skip to content

pip graph command: dependency_file_not_evaluatable on standard pip-tools layered layouts (-c/-r in requirements-dev.in) since #15521 #15556

Description

@emiliolaraop93

Summary

Since the requirements-layering change in #15521, the Dependabot-powered dependency graph (command: "graph") fails with dependency_file_not_evaluatable on the canonical pip-tools two-layer layout (a requirements.in/requirements.txt pair plus a requirements-dev.in/requirements-dev.txt pair where the dev .in references the prod files). Updater image ghcr.io/dependabot/dependabot-updater-pip:f29b76ff090588b0ecd600aabac344cf9059b6bf (2026-07-10) is broken; 508e93d5854a512864ebac5146581c9a1240074a (2026-07-02) was fine on the identical repo state.

Repro layout

backend/requirements.in          # direct prod deps
backend/requirements.txt         # pip-compile --generate-hashes lock of the above
backend/requirements-dev.in      # "-c requirements.txt" + "-r requirements.in" + test deps
backend/requirements-dev.txt     # pip-compile lock of the above

This is the layering workflow from the pip-tools README ("Workflow for layered requirements"), so any repo following it with ≥2 stems in one directory should reproduce.

Error

updater | INFO <job_…> Handled error whilst processing job: dependency_file_not_evaluatable
{message: "InstallationError(\"Could not open constraint file: [Errno 2] No such file or directory: 'dependabot_tmp_dir/requirements.txt'\")"}

Root cause (from reading the code at f29b76f)

Python::DependencyGrapher::RequirementsLayers#files_for_layer builds each layer's manifest group as [primary] + paired-stem files + referenced_requirement_files(primary) + constraints_files, and the transitive -r/-c reference walk is seeded only from the layer's primary file:

  1. For the dev layer the primary is the compiled requirements-dev.txt. Compiled locks contain -r/-c only inside # via annotation comments, which the line-anchored SharedFileFetcher::CHILD_REQUIREMENT_REGEX / CONSTRAINT_REGEX (/^-r…/, /^-c…/) correctly don't match — so the walk finds nothing.
  2. The paired requirements-dev.in — which holds the real -c requirements.txt and -r requirements.in — is added to the group as a support file but is never scanned for references.
  3. The constraints_files fallback only retains files whose basename contains the literal string "constraint", which requirements.txt doesn't.

The group is therefore just [requirements-dev.txt, requirements-dev.in]. Base#build_manifest_group_snapshots (layering activates because there are ≥2 stems/groups) hands a scoped FileParser only those two files; Python::FileParser#parsed_requirement_files writes them into the SharedHelpers temp dir and the helper's parse_requirements() globs *.txt/*.in and runs pip._internal.req.req_file.parse_requirements on each. Parsing requirements-dev.in, pip tries to open the sibling constraint file, raises InstallationError, which REQUIREMENT_FILE_EVALUATION_ERRORS maps to Dependabot::DependencyFileNotEvaluatable.

At 508e93d there was no grouping: the whole directory (all four files) was written to the temp dir together, so the references always resolved.

Note the same failure occurs for the -r requirements.in line as well (the -c just fails first), so the "name your constraint file *constraint*" escape hatch doesn't rescue this layout either.

Suggested fix direction

Seed referenced_requirement_files from every file in the layer group (or at least from the paired .in when the primary is a compiled lock), not just the primary. The .in is precisely where live -r/-c directives are expected to be in a pip-compile workflow.

Why there is no user-side workaround

Moving the -c/-r lines out of requirements-dev.in (into pip-compile CLI flags) makes the graph parse, but breaks Dependabot's own update jobs: PipCompileFileUpdater#pip_compile_options_from_compiled_file reconstructs the compile command from a whitelist of header options that includes neither --constraint nor additional positional source files, so the recompiled dev lock would silently lose the entire prod layer. Layered pip-tools repos are stuck until this is fixed server-side.

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions