odysseus-dev/odysseus · error · HTTPException
Invalid env_prefix
Error message
Invalid env_prefix
What it means
HTTP 400 from the env_prefix normalizer in routes/cookbook_helpers.py (~line 1167) when shlex.split(ep, posix=True) raises ValueError — the env_prefix has unbalanced quotes or an unterminated escape, so it cannot be tokenized into a source-command form.
Source
Thrown at routes/cookbook_helpers.py:1167
"""Build SSH command string with optional port."""
pf = f"-p {port} " if port and port != "22" else ""
return f"ssh {pf}{host} '{cmd}'"
def _safe_env_prefix(ep: str | None) -> str | None:
"""Rewrite a `source <path>` env_prefix so it no-ops if the path is missing.
Prevents `line N: <path>: No such file or directory` errors when a serve
task is launched against a host that doesn't have the expected venv.
Also rewrites leading `~/` → `$HOME/` so the path expands inside double
quotes (bash only tilde-expands unquoted tokens at word start)."""
if not ep:
return ep
import shlex
try:
parts = shlex.split(ep, posix=True)
except ValueError:
raise HTTPException(400, "Invalid env_prefix")
if len(parts) != 2 or parts[0] not in {"source", "."}:
# Bash conda activation emitted by the frontend:
# eval "$(conda shell.bash hook)" && conda activate ENV
m = re.fullmatch(r'eval "\$\(conda shell\.bash hook\)" && conda activate (.+)', ep)
if m:
env = m.group(1).strip()
try:
env_parts = shlex.split(env, posix=True)
except ValueError:
raise HTTPException(400, "Invalid env_prefix")
if len(env_parts) != 1:
raise HTTPException(400, "Invalid env_prefix")
return 'eval "$(conda shell.bash hook)" && conda activate ' + shlex.quote(env_parts[0])
# Plain conda activation, used by Windows/PowerShell and some manual callers.
if len(parts) == 3 and parts[0] == "conda" and parts[1] == "activate":
return "conda activate " + shlex.quote(parts[2])
View on GitHub (pinned to f9235ebbf1)
Solutions
- Balance the quotes: source \"/opt/my venv/bin/activate\"
- Avoid backslashes except as proper escapes; for Windows paths prefer forward slashes
- Generate the string with shlex.quote() so quoting is always well-formed
- Test with python -c 'import shlex; shlex.split(your_string)' before submitting
Example fix
# before env_prefix = "source '/opt/my venv/bin/activate" # after env_prefix = 'source "/opt/my venv/bin/activate"'
Defensive patterns
Strategy: validation
Validate before calling
import shlex
def env_prefix_parses(ep: str) -> bool:
try:
shlex.split(ep, posix=True)
return True
except ValueError:
return False
assert env_prefix_parses(env_prefix), "unbalanced quotes in env_prefix" Prevention
- Build env_prefix with shlex.quote() so quoting stays balanced
- Quote paths containing spaces on both sides
- Prefer standard venv locations without spaces
When it happens
Trigger: env_prefix="source '/opt/venv with space/bin/activate" (opening quote never closed), or a prefix ending in a bare backslash.
Common situations: Paths with spaces quoted on only one side; copy-pasting a Windows path with a stray quote; frontend assembling the string with a broken template that drops the closing quote.
Related errors
- Invalid cmd — could not parse
- await res.text()
- {key} must be an integer
- Invalid JSON
- Expected a JSON object
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/0cc634ac6a15b689.
Report an issue: GitHub.