Skip to content

pixi install --locked fails on every PR because cached pixi.lock is stale (and only main pushes can refresh it) #11330

@xronocode

Description

@xronocode

CI on every PR currently fails ~19 jobs in the test matrix with:

Error: × lock-file not up-to-date with the workspace
The process '/home/runner/.pixi/bin/pixi' failed with exit code 1

(Sample failing run: https://github.com/pydata/xarray/actions/runs/25596596041/job/75143509288 on pull/11327/head. The same pattern shows on main itself, e.g. run 25596621020.)

Root cause

  1. pixi.lock is not committed to the repo (git log -- pixi.lock is empty); it is regenerated by the cache-pixi-lock job and stored in the GitHub Actions cache.
  2. The cache key is pixi-lock_${PIXI_VERSION}_${hashFiles('pixi.toml','pyproject.toml')}_${today}, with restore-keys: ${base}_${yesterday}. So a PR run today on a workspace whose source files haven't changed will fall back to yesterday's cached lock.
  3. cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }} (.github/workflows/ci.yaml#L119) — only push events on main may write the cache.
  4. main has had no merges since 2026-05-04 (Update pre-commit hooks #11319). The cache has therefore not been refreshed for ~6 days.
  5. Over those 6 days, conda-forge / PyPI published new patch versions for some dependencies. pixi install --locked rejects the cached lock because what pixi lock would now produce given the (unchanged) source-file constraints differs from what was cached. Hence "lock-file not up-to-date with the workspace" on every PR.

The failure is not specific to any individual PR's diff — the same error reproduces on main's own CI runs (run 25596621020).

Proposed fixes (any of):

  • Commit pixi.lock and refresh it via a periodic Renovate/Dependabot-style PR. Lock files are designed to be VCSed; the current "regenerate-on-CI-and-cache" approach has the failure mode above when main is quiet.
  • Allow PRs to write the cache (cache-write: true) — but this trades reproducibility for liveness; PRs could pollute the cache with bad locks.
  • Drop --locked from the pixi install invocations in CI — costs reproducibility, allows resolution drift to be silently absorbed.
  • Land any commit on main to force-refresh the cache as a stop-gap (works until the next dependency update).

The first option (commit pixi.lock) is the standard approach for pixi-managed projects and is what pixi's docs themselves recommend.

What I checked

  • All three open recent PRs that triggered the full matrix hit the same error (#11322, #11327, plus older runs on main itself).
  • cache-pixi-lock job for PR docs: Document Index._repr_inline_ in custom-index how-to #11327 succeeded and emitted a non-empty cache key (pixi-lock_latest_c7be59acf5e8379d2b612d3868ff534f986082589a9a7fb33041d9d9be296888_2026-05-09); the downstream test job restored the lock from that key but pixi install --locked then rejected it. The "cache-key cannot be an empty string" line in the verbose log is just the bash source of the Check cache-key step in Parcels-code/pixi-lock/restore@v0.1.0, not the actual error.
  • pyproject.toml was last modified in 73d8d0ab (2026-04-09), so source-file content is stable — confirming the issue is conda-forge/PyPI version drift across the gap, not a workspace edit.

[This is Claude Code on behalf of @xronocode]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions