{"record":{"id":"7982fa79317e00f6","repo":"calesthio/OpenMontage","slug":"unknown-model-model-name","errorCode":null,"errorMessage":"Unknown model: {model_name}","messagePattern":"Unknown model: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/analysis/video_understand.py","lineNumber":399,"sourceCode":"            return model, processor, device\n\n        if model_name == \"blip2\":\n            model_id = \"Salesforce/blip2-opt-2.7b\"\n            processor = Blip2Processor.from_pretrained(model_id)\n            model = Blip2ForConditionalGeneration.from_pretrained(\n                model_id, torch_dtype=torch.float16 if device == \"cuda\" else torch.float32\n            ).to(device)\n            return model, processor, device\n\n        if model_name == \"llava\":\n            model_id = \"llava-hf/llava-1.5-7b-hf\"\n            processor = AutoProcessor.from_pretrained(model_id)\n            model = AutoModelForCausalLM.from_pretrained(\n                model_id, torch_dtype=torch.float16 if device == \"cuda\" else torch.float32\n            ).to(device)\n            return model, processor, device\n\n        raise ValueError(f\"Unknown model: {model_name}\")\n\n    def _analyze_describe(\n        self, frames: list, model_name: str\n    ) -> list[dict[str, Any]]:\n        \"\"\"Generate captions for each frame.\"\"\"\n        import torch\n\n        model, processor, device = self._load_model(model_name)\n        results = []\n\n        for i, img in enumerate(frames):\n            if model_name == \"clip\":\n                # CLIP is not a captioning model; use zero-shot classification\n                # with generic scene descriptions as a caption proxy\n                candidate_texts = [\n                    \"a photo of a person\", \"a photo of a landscape\",\n                    \"a photo of an object\", \"a photo of text\",\n                    \"a photo of an animal\", \"a photo of a building\",","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/analysis/video_understand.py#L381-L417","documentation":"Raised at the end of _load_model when model_name matches none of the supported vision models (the code shows branches for 'clip' and 'llava' preceding the raise). It is a pure input-validation error: the string was not validated against the allowlist before model loading was attempted. Fix is to pass one of the supported model names.","triggerScenarios":"Calling the video-understand describe/analyze tool with model_name values like 'gpt-4v', 'qwen-vl', 'blip', or a typo such as 'CLIP' (case-sensitive) or 'llava1.5'; a config file or CLI flag carrying a model identifier added for a different subsystem.","commonSituations":"Copied model names from a different tool's docs; case mismatch ('Clip' vs 'clip'); version drift after the tool's supported model list changed; default config value not updated after renaming.","solutions":["Pass exactly one of the supported names (check the branches in _load_model — e.g. 'clip' or 'llava')","Validate model_name against the allowlist before calling the tool and fail fast with a helpful message listing valid options","Normalize input with model_name.strip().lower() at the boundary if casing is the issue"],"exampleFix":"// before\nresults = tool.run({\"model\": \"GPT-4V\"})\n\n// after\nALLOWED = {\"clip\", \"llava\"}\nmodel = inputs.get(\"model\", \"clip\").strip().lower()\nif model not in ALLOWED:\n    raise ValueError(f\"model must be one of {sorted(ALLOWED)}, got {model!r}\")\nresults = tool.run({\"model\": model})","handlingStrategy":"validation","validationCode":"ALLOWED_MODELS = {\"clip\", \"llava\"}  # mirror the branches in _load_model\nmodel = inputs.get(\"model\", \"clip\")\nif model not in ALLOWED_MODELS:\n    raise ValueError(f\"model must be one of {sorted(ALLOWED_MODELS)}\")","typeGuard":"def is_supported_model(name: str) -> bool:\n    return name in {\"clip\", \"llava\"}","tryCatchPattern":null,"preventionTips":["Expose the allowlist to config validation so bad names fail at load, not at model download time","Normalize casing (strip().lower()) at the input boundary","Keep the allowlist in one constant and derive both validation and dispatch from it"],"tags":["validation","model-loading","huggingface","configuration"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}