Poetry lock out of sync: diagnose pyproject.toml changes blocking install
Poetry refuses to install when pyproject.toml and poetry.lock are out of sync. Use this diagnostic guide to restore consistency without silently upgrading dependencies.
21 Jul 2026, 23:14 UTC

Recognizable condition
Poetry aborts install, export, or run operations with a lock-consistency error, typically appearing as:
pyproject.toml changed significantly since poetry.lock was last generated. Run `poetry lock` to fix the inconsistency.The lock file contains a content hash of the dependency-relevant sections of pyproject.toml. When this hash no longer matches, Poetry refuses to trust the pinned dependency set. The useful takeaway is to treat this as a trust check: do not force a lock update until you identify why the manifest and lock diverged to avoid accidental dependency upgrades.
Cause and diagnostic table
| Cause | How to spot | Typical trigger |
|---|---|---|
| Dependency or source edits | git diff pyproject.toml shows changes in [project].dependencies, [tool.poetry].dependencies, or [[tool.poetry.source]] | Intentional version bump, adding an extra, or changing a private index URL |
| Root package metadata change | Changes to [tool.poetry].name, [tool.poetry].packages, or [project].name | Renaming the project, moving modules, or migrating to PEP 621 [project] table |
| Poetry major version mismatch | poetry --version differs between the developer and the lock-file creator; lock metadata section differs | Team member uses Poetry 2.x while CI uses Poetry 1.x |
| Stale lock from merge/rebase | git log shows pyproject.toml and poetry.lock changed in separate commits | Parallel PRs touching dependencies merged without a final re-lock |
| Unrefreshed group dependency | poetry check --lock reports inconsistency; new group present in manifest but absent in lock | Adding a dev dependency without running the lock command |
Ordered checks
Capture versions. Run in the repository root. Requires read access.
poetry --version python --versionExpected check: Record the exact Poetry major and Python version. Risk: Different Poetry majors handle
[project]vs[tool.poetry]differently.Validate schema. Check for manifest errors before attempting to fix the lock.
poetry checkExpected check: No schema errors. This ensures you aren't locking an invalid manifest.
Reproduce inconsistency. Where supported by the installed version:
poetry check --lockExpected check: The inconsistency is reproduced without modifying files.
Compare against known-good state.
git diff HEAD^ -- pyproject.toml poetry.lockExpected check: Identify if
pyproject.tomlwas modified without a corresponding update topoetry.lock.Confirm active environment.
poetry env info --path poetry env listExpected check: Path points to a Poetry-managed virtualenv, not a global system Python. Risk:
install --syncon system Python can remove critical OS packages.Reproduce in a clean clone.
git clone <repo> /tmp/repro && cd /tmp/repro && poetry install --dry-runExpected check: Failure reproduces without local state, ruling out local cache or credential issues.
Fixes tied to findings
Intentional manifest change
If the diff shows a deliberate change, re-pin the dependencies without upgrading transitive versions.
poetry lock --no-update
poetry installpoetry lock --no-update refreshes the hash and pins to existing constraints. It will fail if constraints are unsatisfiable or a private index is unreachable. Risk: It does not upgrade dependencies, so a new upper bound may remain unmet.
Poetry major mismatch
Align the team on a single Poetry version and regenerate the lock from the correct base.
# Ensure same version is installed across team/CI
poetry lock --no-update
git diff --exit-code poetry.lockExpected check: Lock diff is limited to metadata and hash, with no unexpected version changes.
Merge produced stale lock
Re-lock from the correct base and verify with tests before committing.
git checkout main
git merge <feature-branch> --no-commit
poetry lock --no-update
# Run test suite here
git commit -m "chore: re-lock after merge"Risk: Running poetry lock without --no-update can silently upgrade transitive dependencies, breaking reproducibility.
Environment mismatch
Recreate the managed environment to ensure a clean state.
poetry env use python3.11
poetry install --sync --dry-run
poetry install --syncAlways use --dry-run first. --sync removes packages not present in the lock file. Never run this against a shared system Python.
Verification after fix
- In a clean clone, run
poetry check --lock. The failure should no longer reproduce. - Run
poetry lock --no-updateand confirmgit diff --exit-code poetry.lockshows no unintended changes. - Confirm the interpreter and installed package version:
poetry run python -c "import sys, importlib.metadata as m; print(sys.executable); print(m.version('your-package-name'))"- Compare
poetry env info --pathacross machines to detect Python-version drift.
Escalation criteria
Escalate to a maintainer or platform owner when:
- The lock cannot be regenerated reproducibly across machines using the same Poetry version.
- Resolution fails only for a private index or specific credential set.
- A security fix requires changing transitive pins and
--no-updateis insufficient. - CI and developer machines disagree after aligning Poetry versions.
- A Poetry major upgrade changes
[project]/[tool.poetry]handling and lock expectations.
Limitations: Exact error text and flags vary between Poetry 1.x and 2.x. PEP 621 [project] support differs by version. Verify flags against your pinned Poetry version before updating CI pipelines. Do not automate poetry lock or poetry update in CI, as it destroys the guarantee of reproducible builds.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.