{"record":{"id":"412afb378af61890","repo":"Hmbown/CodeWhale","slug":"image-inputs-require-an-exact-named-model-with-supported","errorCode":null,"errorMessage":"image inputs require an exact named model with supported image input; Auto is unavailable for images","messagePattern":"image inputs require an exact named model with supported image input; Auto is unavailable for images","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":9861,"sourceCode":"                    req.mode.as_deref(),\n                    req.permission_posture.as_deref(),\n                    req.auto_approve,\n                )?\n            } else {\n                RuntimePolicyProjection::from_persisted(\n                    &thread.mode,\n                    thread.permission_posture.as_deref(),\n                    thread.auto_approve,\n                )\n            };\n        let mode = policy.mode;\n        let requested_model = req.model.as_deref().unwrap_or(&thread.model).to_string();\n        let auto_model = requested_model.trim().eq_ignore_ascii_case(\"auto\");\n        if !image_blocks.is_empty() && (requested_model.is_empty() || requested_model.trim() != requested_model) {\n            bail!(\"image inputs require an exact nonempty named model\");\n        }\n        if !image_blocks.is_empty() && auto_model {\n            bail!(\"image inputs require an exact named model with supported image input; Auto is unavailable for images\");\n        }\n        let cfg_snapshot = self.config.read().clone();\n        let configured_reasoning_preference = cfg_snapshot\n            .reasoning_effort()\n            .map(crate::reasoning_preference::ReasoningEffort::from_setting);\n        // Runtime API precedence is explicit and stable: a turn override wins\n        // over its persisted thread default, which wins over normal config.\n        let reasoning_preference = turn_reasoning_preference\n            .or(thread_reasoning_preference)\n            .or(configured_reasoning_preference);\n        let allow_shell = req.allow_shell.unwrap_or(thread.allow_shell);\n        let trust_mode = req.trust_mode.unwrap_or(thread.trust_mode);\n        let auto_approve = policy.auto_approve();\n        let allowed_tools = req\n            .allowed_tools\n            .clone()\n            .or_else(|| thread.allowed_tools.clone());\n        if req.max_output_tokens.is_some() && auto_model {","sourceCodeStart":9843,"sourceCodeEnd":9879,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L9843-L9879","documentation":"Codewhale's runtime turn handler refuses to start a turn that includes image (attachment) blocks unless the request names a concrete model. The special model value \"auto\" (and empty/whitespace-padded names) trigger dynamic model routing, which cannot guarantee image-input capability, so it is rejected up front with this error.","triggerScenarios":"Calling the runtime turn API (ThreadTurnRequest) with a prompt containing image content blocks while req.model (or the thread's model) is set to \"auto\" (case-insensitive).","commonSituations":"Developers leaving the model selector on Auto/default while pasting a screenshot into the chat; programmatic clients omitting `model` when sending attachments; UI code that resolves \"auto\" to a routing placeholder before dispatch.","solutions":["Set req.model to an exact named model that supports image input (capabilities.image_input == Supported).","Remove the image blocks from the request if Auto routing is required.","Check the resolved route's capabilities via resolve_runtime_thread_route_for_identity before sending images."],"exampleFix":"// before\nlet req = ThreadTurnRequest { model: \"auto\".into(), prompt: prompt_with_screenshot, ..Default::default() };\n// after\nlet req = ThreadTurnRequest { model: \"claude-sonnet-4\".into(), prompt: prompt_with_screenshot, ..Default::default() };","handlingStrategy":"validation","validationCode":"fn can_send_images(req: &ThreadTurnRequest, thread: &Thread) -> bool {\n    let model = req.model.as_deref().unwrap_or(&thread.model).trim();\n    !model.is_empty() && !model.eq_ignore_ascii_case(\"auto\")\n}","typeGuard":"fn is_exact_model(model: &str) -> bool { !model.trim().is_empty() && !model.trim().eq_ignore_ascii_case(\"auto\") }","tryCatchPattern":null,"preventionTips":["Never send attachments while the model picker is on Auto.","Resolve the effective model before constructing the request.","Check the route's image_input capability when enabling image upload UI."],"tags":["model-routing","image-input","validation"],"backgroundTag":"conflicting-config-options","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"}