Skip to content

fix(utils): do not let a blank or non-numeric LK_* debug flag break package import - #7470

Open
Lesereingrape wants to merge 2 commits into
livekit:mainfrom
Lesereingrape:fix/env-int-flags
Open

Lesereingrape wants to merge 2 commits into
livekit:mainfrom
Lesereingrape:fix/env-int-flags

Conversation

@Lesereingrape

Copy link
Copy Markdown

What

LK_DUMP_TTS, LK_OPENAI_DEBUG, LK_KEYTERMS_DEBUG and LIVEKIT_EVALS_VERBOSE are parsed with int(os.getenv(...)) at module scope, so the parse runs while import livekit.agents is still executing. A value that is not an integer raised ValueError there and left the whole package unimportable.

utils.env.resolve_env_int() returns the parsed value, and falls back to the default (logging a warning) when the variable is unset, blank, or not an integer. The six module-level flags now go through it — including the two that read LK_OPENAI_DEBUG, which duplicated the same parse in inference/llm.py and llm/_realtime/openai.py.

import os was dropped from the five files where the flag was its only use.

Why

An empty value is exactly how "not configured" arrives in a container: environment: [LK_DUMP_TTS] in compose, or env: from an unset CI variable, both hand the process "". Measured on current main (98ed3e8):

$ LK_DUMP_TTS= python -c "import livekit.agents"
  File ".../livekit/agents/tts/tts.py", line 36, in <module>
    lk_dump_tts = int(os.getenv("LK_DUMP_TTS", 0))
ValueError: invalid literal for int() with base 10: ''

The same trace, one line different, for LK_OPENAI_DEBUG, LK_KEYTERMS_DEBUG and LIVEKIT_EVALS_VERBOSE. LK_DUMP_TTS=true fails the same way. Every worker, CLI invocation and notebook in the process dies at import — not just the feature the flag belongs to.

The rest of the package already treats the environment the way this PR makes these flags behave:

  • utils/env.py:31 — resolve_env_var skips a variable whose value is "";
  • telemetry/loop_monitor.py:125-141 — _env_seconds returns the default for blank input and warns on anything unparsable; its docstring says invalid values "fall back to the defaults with a warning rather than disabling silently";
  • utils/hw/cpu.py:24-30 — _cpu_count_from_env wraps its float() parse in except ValueError and warns.

So this is the odd one out, and it is the only one of the four that can take the process down.

Valid values keep their meaning: every one of these flags is only ever read in a truthiness test (if lk_dump_tts: etc.), and integers parse as before. I deliberately did not add word parsing ("true", "on") — those now log a warning and fall back to the default instead of raising.

Tests

tests/test_utils_env.py gains TestResolveEnvInt (unset, blank, whitespace, true/on/1.5, and 1/0/" 2 ") plus a regression test that runs import livekit.agents in a subprocess with all four flags blank — that subprocess test fails on main with the trace above and passes with the fix.

  • pytest tests/test_utils_env.py --unit → 17 passed (7 existing + 10 new)
  • ruff check / ruff format --check on all 9 files → clean
  • mypy livekit (strict) → 51 errors, all pre-existing platform/stub issues; the only one in a touched file is inference/llm.py:604 (RealtimeModel.from_model_string return type), which is the same statement as :605 on the base, i.e. untouched by this diff
  • the full pytest --unit --audio_eot gate could not be run here: this is a Windows host and uv sync --all-extras cannot resolve bithuman (no win_amd64 wheel), so I ran the affected module plus tests/test_keyterm_detection_span.py tests/test_evals.py tests/test_agent_tts_node.py (5 passed, 3 deselected) instead

… import

The debug flags are parsed at module scope, so `int(os.getenv(...))` runs while
`import livekit.agents` is still executing. An empty value -- which is how an unset
variable reaches a container -- raised ValueError there, and so did `LK_DUMP_TTS=true`.

`resolve_env_int` follows what the package already does for the rest of its
environment: `resolve_env_var` treats "" as unset, and `_env_seconds` and
`_cpu_count_from_env` fall back to a default with a warning instead of raising.
@Lesereingrape
Lesereingrape requested a review from a team as a code owner September 25, 2026 10:41
devin-ai-integration[bot]

This comment was marked as resolved.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

The openai, google and aws plugins parse their debug flags at import time with
a bare int(os.getenv(...)), so a blank value kept the plugin unimportable even
with the core fix in place. Route them through the same helper and cover the
openai plugin import.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants