{"record":{"id":"ec8d7717840ded74","repo":"Hmbown/CodeWhale","slug":"image-inputs-require-a-model-with-explicitly-supported-image","errorCode":null,"errorMessage":"image inputs require a model with explicitly supported image input","messagePattern":"image inputs require a model with explicitly supported image input","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":9917,"sourceCode":"            self.prepare_runtime_turn_operation(\n                thread_id,\n                Some(operation_key),\n                request_fingerprint,\n                reserved_turn_id,\n            )?\n        } else {\n            None\n        };\n        if let Some(operation) = operation.as_ref()\n            && let Some(original_turn) = self.replay_turn_for_operation(operation)?\n        {\n            return Ok((original_turn, true));\n        }\n        if !image_blocks.is_empty() || req.max_output_tokens.is_some() {\n            let identity = self.provider_identity_for_thread(&cfg_snapshot, &thread)?;\n            let route = resolve_runtime_thread_route_for_identity(&cfg_snapshot, &identity, Some(&requested_model))?;\n            if !image_blocks.is_empty() && route.candidate.capabilities().image_input != codewhale_config::route::CapabilityState::Supported {\n                bail!(\"image inputs require a model with explicitly supported image input\");\n            }\n            if req.max_output_tokens.is_some() && !crate::route_budget::route_supports_output_token_limit(route.identity.provider, route.candidate.protocol()) {\n                bail!(\"maxOutputTokens is unsupported by the selected provider transport\");\n            }\n        }\n        let engine = self.ensure_engine_loaded(&thread).await?;\n\n        let client_preflight_required = {\n            let active = self.active.lock().await;\n            if let Some(active_thread) = active.engines.get(thread_id)\n                && active_thread.active_turn.is_some()\n            {\n                bail!(\"Thread already has an active turn\");\n            }\n            active\n                .engines\n                .get(thread_id)\n                .is_none_or(|state| state.client_preflight_required)","sourceCodeStart":9899,"sourceCodeEnd":9935,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L9899-L9935","documentation":"Even with an exact model named, the runtime validates the resolved route's capabilities and fails the turn if the selected model's route does not declare image_input as CapabilityState::Supported. This is the capability check after routing, complementing the Auto-model checks.","triggerScenarios":"Sending image_blocks with an exact model whose resolved route candidate reports image_input != Supported (e.g. a text-only model like an o1-mini-style or small local model).","commonSituations":"Pointing the thread at a text-only model and attaching a screenshot; provider config drift where a model was previously multimodal; routing tables listing a model under a provider that strips vision support.","solutions":["Switch to a model whose route declares CapabilityState::Supported for image_input.","Remove the image attachments from the turn.","Fix the provider/route config so the intended model exposes image_input: supported."],"exampleFix":"// before\nreq.model = \"text-only-model\".into();\nreq.prompt = blocks_with_image;\n// after\nreq.model = \"gpt-4o\".into(); // image_input: Supported\nreq.prompt = blocks_with_image;","handlingStrategy":"validation","validationCode":"let route = resolve_runtime_thread_route_for_identity(&cfg, &identity, Some(&model))?;\nassert_eq!(route.candidate.capabilities().image_input, CapabilityState::Supported, \"model cannot accept images\");","typeGuard":"fn supports_images(cap: &CapabilityState) -> bool { *cap == CapabilityState::Supported }","tryCatchPattern":null,"preventionTips":["Gate the attach-image UI on the resolved route's image_input capability.","Re-validate capabilities after any provider/route config change.","Keep a list of known vision-capable models per provider."],"tags":["image-input","capabilities","model-selection"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}