Hmbown/CodeWhale · error
Route preference must be nonempty and contain no control…
Error message
Route preference must be nonempty and contain no control characters
What it means
After key validation, set_document trims the value and rejects values that are empty or contain control characters, since route preferences are identifiers/names written into TOML and a blank or control-bearing value would corrupt the config or silently clear the selection.
Solutions
- Trim the value and ensure it is nonempty before calling
- Strip control characters from user input before persisting
- Validate the model/provider name format upstream of the setter
Example fix
// before set(path, "model", "\n")?; // after let v = raw.trim(); anyhow::ensure!(!v.is_empty() && !v.chars().any(char::is_control)); set(path, "model", v)?;
Defensive patterns
Strategy: validation
Validate before calling
let v = value.trim();
if v.is_empty() || v.chars().any(char::is_control) { return Err(anyhow!("route value must be nonempty, control-char free")); } Type guard
fn is_clean_nonempty(s: &str) -> bool { !s.trim().is_empty() && !s.chars().any(char::is_control) } Prevention
- Trim and sanitize all user-supplied model/provider names
- Reject clipboard-pasted values with control bytes
- Never interpolate possibly-empty env vars directly into route values
When it happens
Trigger: Calling set()/set_document() with value "" or a value containing control chars (e.g. stray \n, \t, or terminal escape bytes from clipboard paste).
Common situations: Unset environment variables interpolated empty in shell scripts; copy-paste of model names with hidden control characters; automated edits passing blank placeholders.
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
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- api_key cannot be empty string
- approval_policy ' ' is not allowed by requirements ( )
- budget document_kind must be
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/609bd869e589839d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/route_preferences.rs:362
let mut doc = raw
.parse::<toml_edit::DocumentMut>()
.map_err(|_| anyhow::anyhow!("Could not parse route configuration; contents omitted"))?;
parse_config(raw)?;
persistence::migrate_legacy_route_preferences(path, &mut doc)?;
Ok(doc)
}
/// Edit one route selection in an already-prepared candidate without saving.
/// Callers must prepare migration first and atomically save the final snapshot.
pub fn set_document(
path: &Path,
doc: &mut toml_edit::DocumentMut,
key: &str,
value: &str,
) -> Result<()> {
ensure!(is_route_key(key), "Not a route preference key: {key}");
let value = value.trim();
ensure!(
!value.is_empty() && !value.chars().any(char::is_control),
"Route preference must be nonempty and contain no control characters"
);
if let Some(key) = project_root_key(path, key) {
return persistence::set_document_value(doc, &[key], value);
}
let config = parse_config(&doc.to_string())?;
if key == "provider" {
let identity = config
.resolve_provider_pin_identity(value)
.map_err(anyhow::Error::msg)?;
persistence::set_document_value(
doc,
&["provider"],
identity.persisted_id().unwrap_or(&identity.key),
)?;
// Same root-alias authority as the Runtime/TUI provider writer: a CLI
// switch must not leave the incoming route holding the outgoing one'sView on GitHub (pinned to 73e0f67d83)