Hmbown/CodeWhale · error
cannot be empty
Error message
{label} cannot be empty What it means
`validated_record_id` in the runtime threads store requires every record id (thread, turn, or item) to be a non-empty string before it is used to build a file path or a store query. An empty id would produce an invalid or dangerous path, so it is rejected.
Solutions
- Generate or assign the id before calling the store (e.g. a UUID or ULID).
- Check the id is non-empty at the call site before invoking the store API.
- Fix the deserialization so missing ids surface earlier instead of defaulting to an empty string.
Example fix
// before store.save_turn(&thread_id, &turn_id, record)?; // turn_id == "" // after let turn_id = turn_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); store.save_turn(&thread_id, &turn_id, record)?;
Defensive patterns
Strategy: validation
Validate before calling
fn require_id(id: &str) -> Result<&str, String> { if id.trim().is_empty() { Err("record id is empty".into()) } else { Ok(id) } } Type guard
fn has_id(id: &str) -> bool { !id.trim().is_empty() } Try / catch
match store.save_turn(thread_id, turn_id, record) { Err(e) if e.contains("cannot be empty") => { let id = uuid::Uuid::new_v4().to_string(); retry_with(id) }, Err(e) => return Err(e.into()), Ok(v) => v } Prevention
- Generate ids at record creation, never lazily at save
- Treat optional id fields as required before store calls
- Fail fast on empty ids in deserialization
When it happens
Trigger: Calling `record_path`, `save_turn`, `save_item`, `list_turns_for_thread`, `list_items_for_turn`, or `list_items_for_turns_map` with an id that is empty or all whitespace.
Common situations: A record was never assigned an id before saving; a lookup uses an unset/optional field defaulted to `""`; deserialized records with missing ids.
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
- A pinned task provider requires an explicit model
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- Antigravity cloud-code request has no text contents
- Edit refused: it would leave
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a192c843412f73b0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:297
.find(COMPACTION_SUMMARY_END)
.map(|rel| start + rel + COMPACTION_SUMMARY_END.len());
let mut out = base[..start].trim_end().to_string();
if let Some(end) = end {
let tail = base[end..].trim_start();
if !tail.is_empty() {
if !out.is_empty() {
out.push_str("\n\n");
}
out.push_str(tail);
}
}
out
}
fn validated_record_id<'a>(id: &'a str, label: &str) -> Result<&'a str> {
let trimmed = id.trim();
if trimmed.is_empty() {
bail!("{label} cannot be empty");
}
if trimmed != id {
bail!("{label} cannot contain leading or trailing whitespace");
}
if !trimmed
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
{
bail!("{label} contains unsupported characters");
}
Ok(trimmed)
}
fn agent_mail_workspace_id(workspace: &Path) -> Result<String> {
let canonical = workspace
.canonicalize()
.with_context(|| format!("resolve Agent Mail workspace {}", workspace.display()))?;
let digest = Sha256::digest(canonical.to_string_lossy().as_bytes());View on GitHub (pinned to 73e0f67d83)