Summary
.env.example ships every credential as KEY=<spaces># description. python-dotenv only strips an inline comment when the key has a value; when the key is empty — which is the state of a fresh .env copied from the example — the comment text becomes the value.
The result is that on a fresh install, ~26 environment variables are populated with strings like # FLUX images, Google Veo video, Kling video, MiniMax video,. Tools that gate availability on "is this env var non-empty" then report themselves available, and fail at call time with a 400/401 instead of being cleanly reported as unconfigured.
On my machine the registry claimed 89 of 101 tools available. The true number, after moving the comments onto their own lines, is 60. Roughly 30 tools were falsely green.
Operating system
Windows 11, Python 3.12, python-dotenv 1.2.2
Pipeline
n/a — affects any pipeline that selects a provider
Runtime / renderer
n/a
Steps to reproduce
-
cp .env.example .env (or run make setup, which does this).
-
Add no keys at all.
-
Check what actually gets loaded:
from dotenv import dotenv_values
vals = dotenv_values(".env")
bogus = {k: v for k, v in vals.items() if v and v.lstrip().startswith("#")}
print(len(bogus), "keys hold comment text")
-
Or observe it end to end — with no PIXABAY_API_KEY set, pixabay_video reports available and then issues:
https://pixabay.com/api/videos/?key=%23+Pixabay+stock+footage%2Fimages+%28free%29&q=rain
-> 400 Client Error: Bad Request
That %23+Pixabay+stock+footage... is the comment, URL-encoded and sent as the API key.
Expected behavior
An unset key is empty, and tools depending on it report unavailable with their normal setup instructions.
Actual behavior
An unset key holds its own documentation string, ~30 tools report available, and each fails at runtime with an authentication error that gives no hint about the real cause.
Relevant logs or error output
# exact python-dotenv parsing, isolated:
A_EMPTY_WITH_COMMENT= # some description here
B_WITH_VALUE=realvalue # some description here
C_GLUED=realvalue# some description here
D_EMPTY_BARE=
A_EMPTY_WITH_COMMENT -> '# some description here' <-- the bug
B_WITH_VALUE -> 'realvalue' <-- correctly stripped
C_GLUED -> 'realvalue# some description here'
D_EMPTY_BARE -> '' <-- correct
# sample of what a fresh .env actually loads (26 keys affected):
FAL_KEY = '# FLUX images, Google Veo video, Kling video, MiniMax video,'
OPENAI_API_KEY = '# OpenAI TTS fallback and GPT Image 2 image generation'
ELEVENLABS_API_KEY = '# TTS narration, music generation, sound effects'
KLING_API_KEY = '# Official Kling API key; enables video, image, TTS, avatar,'
SUNO_API_KEY = '# Suno AI music generation (full songs, instrumentals, any g'
Suggested fix
Move each comment onto its own line above its key in .env.example:
-FAL_KEY= # FLUX images, Google Veo video, Kling video, MiniMax video
+# FLUX images, Google Veo video, Kling video, MiniMax video
+FAL_KEY=
That fixes it for every new user with no code change.
A second, related papercut worth handling in the same pass: row C_GLUED above. A user who pastes a key immediately before the # (easy to do, since the cursor lands right after =) gets the # appended to their credential and a 401 that looks like a bad key. I hit this with a valid Pexels key — the key worked fine once the trailing # was stripped. Moving the comments off the key lines removes this failure mode too.
Optional hardening: treat a value beginning with # as unset when resolving credentials, so a malformed .env degrades to "unconfigured" rather than "configured with garbage".
Worth noting this likely inflates the capability counts anyone sees after a fresh make setup, including in the README.
Summary
.env.exampleships every credential asKEY=<spaces># description. python-dotenv only strips an inline comment when the key has a value; when the key is empty — which is the state of a fresh.envcopied from the example — the comment text becomes the value.The result is that on a fresh install, ~26 environment variables are populated with strings like
# FLUX images, Google Veo video, Kling video, MiniMax video,. Tools that gate availability on "is this env var non-empty" then report themselves available, and fail at call time with a 400/401 instead of being cleanly reported as unconfigured.On my machine the registry claimed 89 of 101 tools available. The true number, after moving the comments onto their own lines, is 60. Roughly 30 tools were falsely green.
Operating system
Windows 11, Python 3.12, python-dotenv 1.2.2
Pipeline
n/a — affects any pipeline that selects a provider
Runtime / renderer
n/a
Steps to reproduce
cp .env.example .env(or runmake setup, which does this).Add no keys at all.
Check what actually gets loaded:
Or observe it end to end — with no
PIXABAY_API_KEYset,pixabay_videoreportsavailableand then issues:That
%23+Pixabay+stock+footage...is the comment, URL-encoded and sent as the API key.Expected behavior
An unset key is empty, and tools depending on it report
unavailablewith their normal setup instructions.Actual behavior
An unset key holds its own documentation string, ~30 tools report
available, and each fails at runtime with an authentication error that gives no hint about the real cause.Relevant logs or error output
Suggested fix
Move each comment onto its own line above its key in
.env.example:That fixes it for every new user with no code change.
A second, related papercut worth handling in the same pass: row
C_GLUEDabove. A user who pastes a key immediately before the#(easy to do, since the cursor lands right after=) gets the#appended to their credential and a 401 that looks like a bad key. I hit this with a valid Pexels key — the key worked fine once the trailing#was stripped. Moving the comments off the key lines removes this failure mode too.Optional hardening: treat a value beginning with
#as unset when resolving credentials, so a malformed.envdegrades to "unconfigured" rather than "configured with garbage".Worth noting this likely inflates the capability counts anyone sees after a fresh
make setup, including in the README.