odysseus-dev/odysseus · error · HTTPException

Invalid repo_id — must be <org>/<name>, an Ollama name:tag,

Error message

Invalid repo_id — must be <org>/<name>, an Ollama name:tag, or a cached local model id

What it means

HTTP 400 from _validate_serve_model_id() in routes/cookbook_helpers.py. The value must match one of three accepted shapes: _REPO_ID_RE (HF <org>/<name>), _LOCAL_MODEL_ID_RE (cached local model id), or _OLLAMA_MODEL_ID_RE (Ollama name:tag). Anything else — spaces, URLs, shell metacharacters, unusual punctuation — is rejected.

Source

Thrown at routes/cookbook_helpers.py:76

    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


def _validate_token(v: str | None) -> str | None:
    if v is None or v == "":
        return None
    if not _TOKEN_RE.match(v):
        raise HTTPException(400, "Invalid token characters")
    return v

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Use an HF id (mistralai/Mistral-7B-Instruct-v0.2), an Ollama name:tag (llama3:8b), or a cached local model id exactly as the cache keys it
  2. Strip whitespace and quotes before sending
  3. Inspect _REPO_ID_RE, _LOCAL_MODEL_ID_RE and _OLLAMA_MODEL_ID_RE in routes/cookbook_helpers.py to see which shape your value violates
  4. For a brand-new local model, download/register it first so it matches the cached-id grammar

Example fix

// before
{"repo_id": "models--meta-llama--Meta-Llama-3-8B/snapshots/abc123"}
// after
{"repo_id": "meta-llama/Meta-Llama-3-8B"}
Defensive patterns

Strategy: validation

Validate before calling

import re
REPO = re.compile(r"^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$")
OLLAMA = re.compile(r"^[A-Za-z0-9._-]+:[A-Za-z0-9._-]+$")

def classify_model_id(v: str):
    v = (v or "").strip()
    if REPO.match(v):
        return "hf"
    if OLLAMA.match(v):
        return "ollama"
    return None  # compare local cache keys separately

if classify_model_id(rid) is None:
    raise ValueError(f"unsupported model id: {rid!r}")

Type guard

function looksLikeModelId(v: string): boolean {
  const t = v.trim();
  return /^[\w.-]+\/[\w.-]+$/.test(t) || /^[\w.-]+:[\w.-]+$/.test(t);
}

Prevention

When it happens

Trigger: POST serve with repo_id values like "meta-llama/Meta-Llama-3-8B " (trailing space), "https://huggingface.co/org/name", "org/name;rm -rf", or a local filesystem path that does not fit _LOCAL_MODEL_ID_RE.

Common situations: Users pasting HF URLs or local paths where an id is expected; whitespace from copy-paste; attempted command injection through the model field; sending a Docker-style image reference (org/repo:tag), which is not one of the three accepted grammars.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/a42acc2b868916df. Report an issue: GitHub.