{"record":{"id":"46d65065f8684ef0","repo":"Hmbown/CodeWhale","slug":"model-name-cannot-be-empty","errorCode":null,"errorMessage":"Model name cannot be empty","messagePattern":"Model name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/lib.rs","lineNumber":4270,"sourceCode":"                    \"--provider\".to_string()\n                } else {\n                    provider_source_label(resolved_runtime.provider_source)\n                }\n            );\n            println!(\n                \"model_source: {}\",\n                if queried.is_some() {\n                    \"argument\"\n                } else {\n                    resolved_runtime.model_source.as_str()\n                }\n            );\n            Ok(())\n        }\n        ModelCommand::Set { model } => {\n            let trimmed = model.trim();\n            if trimmed.is_empty() {\n                bail!(\"Model name cannot be empty\");\n            }\n            let canonical = match trimmed.to_ascii_lowercase().as_str() {\n                \"pro\" | \"deepseek-v4pro\" => \"deepseek-v4-pro\",\n                \"flash\" | \"deepseek-v4flash\" => \"deepseek-v4-flash\",\n                \"auto\" => \"auto\",\n                _ => trimmed,\n            };\n            store.config.default_text_model = Some(canonical.to_string());\n            store.save()?;\n            println!(\"Default model set to '{canonical}'\");\n            Ok(())\n        }\n    }\n}\n\n/// The TUI passthrough a thread subcommand delegates as, if it delegates.\n///\n/// Exhaustive on purpose: a future `ThreadCommand` variant that starts a","sourceCodeStart":4252,"sourceCodeEnd":4288,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/cli/src/lib.rs#L4252-L4288","documentation":"`codewhale model set <model>` trims the argument and refuses an empty string: an empty default model would break every later model resolution, so Codewhale validates before saving. Note that after this check the value is canonicalized (`pro`/`deepseek-v4pro` → `deepseek-v4-pro`, `flash` → `deepseek-v4-flash`, `auto` passes through) and persisted to config.","triggerScenarios":"`codewhale model set \"\"`, `codewhale model set \"   \"`, or scripts passing an unset shell variable (`MODEL=` or `$UNDEFINED`) as the model name.","commonSituations":"Shell scripts with unbound/empty variables; CI overriding the model with an empty string; users trying to 'reset' the model by setting it to empty.","solutions":["Pass a concrete model name (e.g. `deepseek-v4-pro`) or an alias (`pro`, `flash`, `auto`)","Fix the script: default the variable first, e.g. `MODEL=${MODEL:-auto}`","To clear a default model, unset the config key rather than setting an empty one"],"exampleFix":"# before\n$ MODEL= codewhale model set \"$MODEL\"\n# Model name cannot be empty\n\n# after\n$ MODEL=${MODEL:-auto} codewhale model set \"$MODEL\"","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\nmodel=\"${MODEL:-}\"\nmodel=\"$(printf '%s' \"$model\" | tr -d '[:space:]')\"\n[ -n \"$model\" ] || model=\"auto\"\ncodewhale model set \"$model\"","typeGuard":"fn is_valid_model_name(name: &str) -> bool {\n    !name.trim().is_empty()\n}","tryCatchPattern":null,"preventionTips":["Always default the variable: `model=${MODEL:-auto}`","To clear a default model, unset the config key; never set it to an empty string"],"tags":["model","validation","empty-input","cli","config"],"backgroundTag":"invalid-model-name","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}