Posted on:March 10, 2026 at 12:00 AM

Fixing Poetry Virtualenv Path After Moving a Project Directory

Fixing Poetry Virtualenv Path After Moving a Project Directory

Fixing Poetry Virtualenv Path After Moving a Project Directory

The Problem

After moving a Python project from one directory to another:

/Users/you/projects/my-python-app

/Users/you/new-projects/my-python-app

Poetry kept reporting the old virtualenv path:

 poetry env info

Virtualenv
Python:         3.11.11
Path:           /Users/you/projects/my-python-app/.venv
Valid:          False

Despite running poetry env remove, poetry env use, and even deleting .venv entirely, the old path persisted.

The Investigation

Red Herrings

Several things were checked but turned out not to be the cause:

  1. Poetry cache directories (~/Library/Caches/pypoetry/) - contained package artifacts, not virtualenv paths
  2. Poetry config files (~/Library/Application Support/pypoetry/config.toml) - correctly set virtualenvs.in-project = true
  3. Project files (pyproject.toml, poetry.lock) - no hardcoded paths
  4. .venv/pyvenv.cfg - did not contain the old path
  5. Poetry hash-based caching - Poetry uses SHA256 hashes of project paths, but no cached hash files were found

The Real Culprit

The issue was found by checking environment variables:

 env | grep -i virtual
VIRTUAL_ENV=/Users/you/projects/my-python-app/.venv

The VIRTUAL_ENV environment variable was set to the old path!

Root Cause

The project used direnv with a .envrc file that sources the virtualenv:

# .envrc
dotenv
source .venv/bin/activate

When the project was moved:

  1. The old .venv directory was moved along with the project
  2. The .venv/bin/activate script contained a hardcoded VIRTUAL_ENV path pointing to the old location
  3. direnv cached this environment when first entering the directory
  4. Even after recreating .venv (with the correct path in its activate script), direnv continued using its cached environment

Poetry reads the VIRTUAL_ENV environment variable to determine the current virtualenv, so it kept reporting the old (now invalid) path.

The Solution

After recreating the .venv directory (which Poetry did correctly):

rm -rf .venv && poetry install

The fix was simply to reload direnv to pick up the new activate script:

direnv reload

Or leave and re-enter the directory:

cd .. && cd -

Key Takeaways

  1. Poetry’s env info reflects VIRTUAL_ENV - If this environment variable is set, Poetry reports it rather than discovering the virtualenv fresh.

  2. direnv caches environment state - When you source a script via direnv, the resulting environment is cached. Changes to the underlying script require direnv reload.

  3. Virtualenv activate scripts contain hardcoded paths - The VIRTUAL_ENV variable in .venv/bin/activate is set to an absolute path at creation time. Moving the directory breaks this.

  4. The fix is often simpler than expected - After extensive investigation of Poetry internals, the solution was a simple direnv reload.

Prevention

When moving a Python project that uses Poetry + direnv:

  1. Delete the old .venv before or after moving
  2. Run poetry install to create a fresh virtualenv
  3. Run direnv reload to refresh the cached environment

Or more simply: after moving any project with direnv, always run direnv reload.

Related Posts