Hmbown/CodeWhale · error
Model name cannot be empty
Error message
Model name cannot be empty
What it means
Model subcommand argument validation: a model was explicitly supplied as an empty string. An explicitly requested model must be non-empty because an empty id cannot be resolved against any provider; the guard fires before the command runs.
Solutions
- Pass a non-empty model name: `codewhale model set <model>`.
- Check the source variable in scripts: `echo "$MODEL"` to confirm it is populated.
- Use `codewhale model list` (or providers export) to find valid model names.
Example fix
// before
codewhale model set "$MODEL" # MODEL empty
// after
: "${MODEL:?MODEL must be set}" && codewhale model set "$MODEL" Defensive patterns
Strategy: validation
Validate before calling
let trimmed = model.trim();
if trimmed.is_empty() {
eprintln!("refusing to call 'model set' with an empty name");
std::process::exit(2);
} Try / catch
if let Err(e) = run_model_set(model) {
if e.to_string() == "Model name cannot be empty" {
eprintln!("$MODEL is unset or blank; export MODEL=<name> first");
} else { return Err(e); }
} Prevention
- Guard shell variables with :? before interpolating into CLI args.
- Use `codewhale model list` to pick a concrete model id instead of typing from memory.
- In scripts, assert the model argument is non-empty before dispatching.
When it happens
Trigger: Running `codewhale model set ""` or `codewhale model set " "` — trimmed.is_empty() — before canonical_model_for_set is applied.
Common situations: Shell variable holding the model name is empty/unset; copy-paste dropped the model id; scripted invocation with a missing positional argument consumed as empty string.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- speech requires a TTS model
- A positive pull request number is required
- API key contains invalid control characters
- API key id must be lowercase hex characters — the part…
- API key input is unexpectedly large
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/46d65065f8684ef0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/lib.rs:4887
);
println!(
"model_source: {}",
if queried.is_some() {
"argument"
} else {
// This branch is reachable only for an explicit
// subcommand provider with no requested model. The model
// therefore came from that provider's default, not from
// the configured runtime route we deliberately overrode.
"provider default"
}
);
Ok(())
}
ModelCommand::Set { model } => {
let trimmed = model.trim();
if trimmed.is_empty() {
bail!("Model name cannot be empty");
}
let canonical = canonical_model_for_set(trimmed);
codewhale_tui::route_preferences::set(store.path(), "model", canonical)?;
store.reload()?;
println!("Default model set to '{canonical}'");
Ok(())
}
}
}
/// The TUI passthrough a thread subcommand delegates as, if it delegates.
///
/// Exhaustive on purpose: a future `ThreadCommand` variant that starts a
/// session has to state its passthrough here, where the caller below routes it
/// through the one command builder that applies the telemetry floor.
fn thread_delegation(command: &ThreadCommand) -> Option<Vec<String>> {
match command {
ThreadCommand::Resume { thread_id } => Some(vec!["resume".to_string(), thread_id.clone()]),View on GitHub (pinned to 73e0f67d83)