odysseus-dev/odysseus · error · HTTPException
Invalid repo_id — must be <org>/<name> using [A-Za-z0-9._-]
Error message
Invalid repo_id — must be <org>/<name> using [A-Za-z0-9._-]
What it means
HTTP 400 from _validate_repo_id() in routes/cookbook_helpers.py. The value must fully match _REPO_ID_RE, i.e. a Hugging Face style <org>/<name> built only from [A-Za-z0-9._-]. Empty, None, extra slashes, spaces, unicode, or a missing org/name split all fail.
Source
Thrown at routes/cookbook_helpers.py:67
# shell-safe: none of ``; & | ` $ '' "" () {}`` newlines etc. are in ``[\w. -]``,
# so injection vectors remain rejected. A leading ~ is expanded to $HOME at
# command-build time. (Drive letters stay ASCII: ``[A-Za-z]:``.)
_LOCAL_DIR_RE = re.compile(r"^~?(?:/[\w. -]*)+$|^~$")
_WINDOWS_LOCAL_DIR_RE = re.compile(r"^[A-Za-z]:[\\/](?:[\w. -]+(?:[\\/][\w. -]+)*[\\/]?)?$")
_WINDOWS_DRIVE_PATH_RE = re.compile(r"^[A-Za-z]:[\\/]")
def _git_bash_path(path: str) -> str:
m = re.match(r"^([A-Za-z]):[\\/](.*)$", path)
if not m:
return path
drive, rest = m.groups()
return f"/{drive.lower()}/{rest.replace(chr(92), '/')}"
def _validate_repo_id(v: str | None) -> str:
if not v or not _REPO_ID_RE.match(v):
raise HTTPException(400, "Invalid repo_id — must be <org>/<name> using [A-Za-z0-9._-]")
return v
def _validate_serve_model_id(v: str | None) -> str:
if not v:
raise HTTPException(400, "repo_id is required")
if _REPO_ID_RE.match(v) or _LOCAL_MODEL_ID_RE.match(v) or _OLLAMA_MODEL_ID_RE.match(v):
return v
raise HTTPException(400, "Invalid repo_id — must be <org>/<name>, an Ollama name:tag, or a cached local model id")
def _validate_include(v: str | None) -> str | None:
if v is None or v == "":
return None
if not _INCLUDE_RE.match(v):
raise HTTPException(400, "Invalid include pattern")
return v
View on GitHub (pinned to f9235ebbf1)
Solutions
- Send the exact Hugging Face repo id: <org>/<name>, e.g. mistralai/Mistral-7B-Instruct-v0.2
- Strip whitespace and drop the https://huggingface.co/ prefix before sending
- If you meant an Ollama or local cached model, use an endpoint whose validator accepts those (_validate_serve_model_id)
- Check _REPO_ID_RE at the top of routes/cookbook_helpers.py for the authoritative pattern
Example fix
// before
{"repo_id": "https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.2"}
// after
{"repo_id": "mistralai/Mistral-7B-Instruct-v0.2"} Defensive patterns
Strategy: validation
Validate before calling
import re
REPO_ID_RE = re.compile(r"^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$")
def is_valid_repo_id(v):
return bool(v) and bool(REPO_ID_RE.match(v))
assert is_valid_repo_id("mistralai/Mistral-7B-Instruct-v0.2") Try / catch
try:
r = client.post("/cookbook/download", json={"repo_id": rid})
except HTTPException as e:
if e.status_code == 400 and "repo_id" in e.detail:
rid = prompt_user_for_exact_hf_id()
else:
raise Prevention
- Send the bare HF id <org>/<name>, never the full URL
- Strip whitespace and URL prefixes client-side
- Reserve Ollama/local ids for endpoints that use _validate_serve_model_id
When it happens
Trigger: Calling a cookbook endpoint that validates repo_id with values like "model" (no slash), "org/a/b" (two slashes), "org/name extra" (space), "" or null, or an Ollama id ("llama3:8b") sent to an endpoint that only accepts HF repo ids.
Common situations: Passing a bare model name without the org; copying a full HF URL (https://huggingface.co/org/name) instead of the id; trailing whitespace or invisible unicode from copy-paste.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/43d2021dd4d418b9.
Report an issue: GitHub.