calesthio/OpenMontage · error · ValueError
model must be one of: sora-2, sora-2-pro
Error message
model must be one of: sora-2, sora-2-pro
What it means
ValueError raised by SoraVideo._normalize_model when the 'model' input, after strip+lowercase, is not in _ALLOWED_MODELS. Only the two OpenAI video models 'sora-2' and 'sora-2-pro' are accepted; anything else — including plausible names like 'sora', 'sora-2-turbo', or other providers' model ids — is rejected before any API call.
Source
Thrown at tools/video/sora_video.py:239
if cls._version_tuple(getattr(openai, "__version__", "")) < _MIN_OPENAI_VERSION:
return False
return hasattr(OpenAI(), "videos")
@staticmethod
def _version_tuple(version: str) -> tuple[int, int, int]:
parts = []
for part in version.split(".")[:3]:
digits = "".join(ch for ch in part if ch.isdigit())
parts.append(int(digits or "0"))
while len(parts) < 3:
parts.append(0)
return tuple(parts)
@staticmethod
def _normalize_model(inputs: dict[str, Any]) -> str:
model = str(inputs.get("model", _DEFAULT_MODEL)).strip().lower()
if model not in _ALLOWED_MODELS:
raise ValueError("model must be one of: sora-2, sora-2-pro")
return model
@staticmethod
def _normalize_size(inputs: dict[str, Any], model: str) -> str:
default_size = "1280x720" if inputs.get("aspect_ratio") == "16:9" else _DEFAULT_SIZE
size = str(inputs.get("size", default_size)).strip().lower()
allowed = {"1280x720", "720x1280"} if model == "sora-2" else set(_ALLOWED_SIZES)
if size not in allowed:
raise ValueError(f"size must be one of: {', '.join(sorted(allowed))} for model {model}")
return size
@staticmethod
def _normalize_seconds(inputs: dict[str, Any]) -> str:
seconds = str(inputs.get("seconds") or inputs.get("duration") or _DEFAULT_SECONDS).strip().lower()
seconds = seconds[:-1] if seconds.endswith("s") else seconds
if seconds not in _ALLOWED_SECONDS:
raise ValueError("seconds must be one of: 4, 8, 12")
return secondsView on GitHub (pinned to 95e1c3d0ab)
Solutions
- Use exactly 'sora-2' or 'sora-2-pro'.
- If your deployment uses a custom name (Azure-style), remove the model override and let the default apply, or map your deployment name to one of the allowed values at your call site.
- Omit model to fall back to _DEFAULT_MODEL.
Example fix
# before
inputs = {"model": "sora-2-turbo"}
# after
inputs = {"model": "sora-2-pro"} Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = {"sora-2", "sora-2-pro"}
model = str(inputs.get("model", "sora-2")).strip().lower()
if model not in ALLOWED:
inputs["model"] = "sora-2" Type guard
def is_valid_sora_model(v) -> bool:
return str(v).strip().lower() in {"sora-2", "sora-2-pro"} Prevention
- Source model names from a constant list shared with your UI/config, never free text.
- Map external deployment names to the two allowed values at your boundary.
When it happens
Trigger: Passing model='sora', model='soravideo', model='dangao-2' (the Chinese-market alias), or leaving trailing junk like 'sora-2 '. (Note trailing whitespace alone is stripped, so ' Sora-2 ' is fine.)
Common situations: Model lists copy-pasted from news articles or other gateways (Azure OpenAI deployments use custom deployment names like 'my-sora-deployment'); version drift after new Sora releases when users guess at names.
Related errors
- size must be one of: {', '.join(sorted(allowed))} for model
- seconds must be one of: 4, 8, 12
- ${res.status} ${url}
- fetch failed ${r.status}: ${url}
- path escapes project
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/1d94ebc4ff5cfe90.
Report an issue: GitHub.