Skip to content

VIRTUAL_ENV env var prevents poetry -C from finding the target project's in-project .venv #10773

@Pwuts

Description

@Pwuts

Description

When VIRTUAL_ENV is set in the environment, poetry -C <dir> ignores the target project's in-project .venv and uses whatever VIRTUAL_ENV points to instead. This causes Poetry to use the wrong Python version and potentially install into the wrong environment.

This is particularly problematic for:

  • AI coding assistants (e.g. Claude Code) that run Poetry commands in a subprocess where VIRTUAL_ENV may be set to an unrelated path (e.g. /usr)
  • Pre-commit hooks that run poetry -C <dir> install
  • CI environments where VIRTUAL_ENV may be inherited from the runner
  • Monorepos where you activate one project's venv but use -C to operate on another

In the case of Claude Code (Anthropic's AI coding CLI), the subprocess environment has VIRTUAL_ENV=/usr set, which causes all poetry -C commands to use system Python 3.14 instead of the project's .venv with Python 3.13 — breaking installs when the project constrains python < 3.14.

Reproduction

# Works — finds in-project .venv with Python 3.13
$ poetry -C project_a env info
Virtualenv Python: 3.13.12, Path: .venv

# Broken — VIRTUAL_ENV overrides .venv discovery
$ VIRTUAL_ENV=/usr poetry -C project_a env info
Virtualenv Python: 3.14.3, Path: /usr

# Real-world: Claude Code's subprocess environment
$ VIRTUAL_ENV=/usr poetry -C project_a install
# → "Current Python version (3.14.3) is not allowed by the project"

Root cause

In poetry/utils/env/env_manager.py, the get() method:

env_prefix = os.environ.get("VIRTUAL_ENV", os.environ.get("CONDA_PREFIX"))
in_venv = env_prefix is not None and conda_env_name != "base"

if not in_venv or env is not None:
    # In-project .venv discovery happens HERE — but is skipped when VIRTUAL_ENV is set
    if self.in_project_venv_exists():
        venv = self.in_project_venv
        return VirtualEnv(venv)

# Falls through to blindly trust VIRTUAL_ENV:
if env_prefix is not None:
    prefix = Path(env_prefix)
return VirtualEnv(prefix, base_prefix)

When VIRTUAL_ENV is set, in_venv = True, so the condition not in_venv or env is not None is False. The in-project .venv check is entirely skipped and Poetry blindly uses Path(VIRTUAL_ENV).

Suggested fix

When -C/--directory is explicitly used, Poetry should prioritize the target project's in-project .venv over the VIRTUAL_ENV environment variable. The VIRTUAL_ENV from the calling environment is not relevant to the target project.

Workarounds

  1. Unset VIRTUAL_ENV before running Poetry:
    unset VIRTUAL_ENV && poetry -C project_a install
  2. cd into the project directory instead of using -C:
    cd project_a && poetry install

Poetry Installation Method

install.python-poetry.org

Operating System

Fedora 43

Poetry Version

2.3.2

Poetry Configuration

cache-dir = "/home/reinier/.cache/pypoetry"
data-dir = "/home/reinier/.local/share/pypoetry"
installer.max-workers = null
installer.no-binary = null
installer.only-binary = null
installer.parallel = true
installer.re-resolve = false
keyring.enabled = true
python.installation-dir = "{data-dir}/python"  # /home/reinier/.local/share/pypoetry/python
requests.max-retries = 0
solver.lazy-wheel = true
system-git-client = false
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/reinier/.cache/pypoetry/virtualenvs
virtualenvs.prompt = "{project_name}-py{python_version}"
virtualenvs.use-poetry-python = false

Python Sysconfig

sysconfig.log
Platform: "linux-x86_64"
Python version: "3.13"
Current installation scheme: "posix_prefix"

Paths:
  data = "/usr/local"
  include = "/usr/include/python3.13"
  platinclude = "/usr/include/python3.13"
  platlib = "/usr/local/lib64/python3.13/site-packages"
  platstdlib = "/usr/local/lib64/python3.13"
  purelib = "/usr/local/lib/python3.13/site-packages"
  scripts = "/usr/local/bin"
  stdlib = "/usr/lib64/python3.13"

Poetry Runtime Logs

poetry-runtime.log
$ VIRTUAL_ENV=/usr poetry -vvv -C autogpt_platform/backend env info
Loading configuration file /home/reinier/.config/pypoetry/config.toml

Virtualenv
Python:         3.14.3
Implementation: CPython
Path:           /usr
Executable:     /usr/bin/python
Valid:          True

Base
Platform:   linux
OS:         posix
Python:     3.14.3
Path:       /usr
Executable: /usr/bin/python3.14

$ poetry -vvv -C autogpt_platform/backend env info  # without VIRTUAL_ENV — works correctly
Loading configuration file /home/reinier/.config/pypoetry/config.toml

Virtualenv
Python:         3.13.12
Implementation: CPython
Path:           .venv
Executable:     .venv/bin/python
Valid:          True

Base
Platform:   linux
OS:         posix
Python:     3.13.12
Path:       /usr
Executable: /usr/bin/python3.13

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugSomething isn't working as expectedstatus/triageThis issue needs to be triaged

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions