odysseus-dev/odysseus · error · HTTPException
Invalid include pattern
Error message
Invalid include pattern
What it means
HTTP 400 from _validate_include() in routes/cookbook_helpers.py when a non-empty include pattern fails _INCLUDE_RE. Include patterns are constrained file-glob fragments used as download filters; the regex limits allowed characters/shape, so arbitrary glob syntax or shell text is rejected. Empty string and None are allowed and normalize to None.
Source
Thrown at routes/cookbook_helpers.py:83
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
def load_stored_hf_token(*, state_path: Path | str | None = None) -> str:
"""Return the decrypted HF token from cookbook_state.json, else env fallback."""
path = Path(state_path) if state_path else Path(os.environ.get("DATA_DIR", "data")) / "cookbook_state.json"
token = ""
if path.exists():
try:
state = json.loads(path.read_text(encoding="utf-8"))View on GitHub (pinned to f9235ebbf1)
Solutions
- Simplify the pattern to a plain glob like *.safetensors or *.json
- Read _INCLUDE_RE at the top of routes/cookbook_helpers.py and conform to its allowed characters
- Omit include entirely when you want all files
Example fix
// before
{"include": "**/*.{safetensors,json}"}
// after
{"include": "*.safetensors"} Defensive patterns
Strategy: validation
Validate before calling
import re
INCLUDE_RE = re.compile(r"^[A-Za-z0-9*._/\[\]-]+$") # mirror the server's _INCLUDE_RE; read the real one from cookbook_helpers.py
def safe_include(v):
if v is None or v == "":
return None
v = v.strip()
if not INCLUDE_RE.match(v):
raise ValueError("include pattern uses unsupported characters")
return v Prevention
- Stick to simple globs (*.safetensors, *.json)
- Omit include when you want everything
- Do not port rsync/find glob syntax (**, braces, !) into this field
When it happens
Trigger: Passing include="**/*.{safetensors,json}", include="src/**; rm -rf", include="../../../etc/passwd", or any pattern containing characters outside _INCLUDE_RE's allowlist.
Common situations: Users copying rsync/find glob syntax (**, braces, negation !) that the allowlist does not support; attempting traversal paths; embedding spaces or shell operators that could break the underlying download-filter command.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/ceca26da1d25a409.
Report an issue: GitHub.