Skip to content

Invalid POETRY_REQUESTS_TIMEOUT can fail at import time instead of using config normalization #10969

Description

@MicroMilo

Summary

Setting POETRY_REQUESTS_TIMEOUT to a non-integer value can make even unrelated commands such as poetry --version fail during import with a raw ValueError traceback.

Reproduction

POETRY_REQUESTS_TIMEOUT=abc python -m poetry --version

Actual behavior

The process fails during import with a traceback ending in:

ValueError: invalid literal for int() with base 10: 'abc'

The failing line is the import-time conversion of the environment variable:

REQUESTS_TIMEOUT = int(os.getenv("POETRY_REQUESTS_TIMEOUT", 15))

Expected behavior

Invalid POETRY_REQUESTS_TIMEOUT values should ideally be reported as a Poetry configuration error that names the variable and expected type, rather than as an import-time traceback. Also, commands that do not use HTTP requests, such as poetry --version, probably should not fail because an HTTP timeout environment variable is malformed.

If the intended product semantics are that malformed environment variables are allowed to fail at import time, it would be helpful to state that explicitly. Otherwise, this looks inconsistent with Poetry's existing typed configuration normalization path.

Why int_normalizer makes this look inconsistent

Poetry already has a configuration normalization mechanism for environment-derived settings. In Config.get, environment variables are looked up and passed through the appropriate normalizer:

env = "POETRY_" + "_".join(k.upper().replace("-", "_") for k in keys)
env_value = os.getenv(env)
if env_value is not None:
    return self.process(self._get_normalizer(setting_name)(env_value))

For integer settings, Poetry explicitly uses int_normalizer:

@staticmethod
def _get_normalizer(name: str) -> Callable[[str], Any]:
    if name in {
        "installer.max-workers",
        "requests.max-retries",
        "solver.lazy-wheel",
    }:
        return int_normalizer

That means config-backed integer values already have a single typed conversion point. POETRY_REQUESTS_TIMEOUT, however, bypasses this path and is converted directly in poetry.utils.constants at import time:

REQUESTS_TIMEOUT = int(os.getenv("POETRY_REQUESTS_TIMEOUT", 15))

The parsed value is later consumed as an HTTP timeout, for example by request/authenticator code. The contract drift is that this timeout behaves like a typed numeric configuration, but it does not use the existing typed configuration normalizer and therefore fails with a raw import-time ValueError.

Possible fixes

A few possible directions:

  1. Move this setting into Poetry's normal config path and use the existing integer normalization mechanism.
  2. Delay parsing until the timeout is actually needed by HTTP code.
  3. Catch ValueError and raise a Poetry-facing configuration error such as POETRY_REQUESTS_TIMEOUT must be an integer number of seconds.

A regression test could set POETRY_REQUESTS_TIMEOUT=abc and assert that startup does not produce a raw traceback, especially for commands that do not perform HTTP requests.


Submitted with PilotDeck (OpenBMB/PilotDeck).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions