Hmbown/CodeWhale · error
{label} cannot contain leading or trailing whitespace
Error message
{label} cannot contain leading or trailing whitespace What it means
validated_record_id rejects ids where trim() changes the string, i.e. ids with leading or trailing whitespace. Because ids are used verbatim as path components and lookup keys, invisible padding would create records that can never be addressed again, so it is treated as data corruption at the door.
Source
Thrown at crates/tui/src/runtime_threads.rs:268
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());
let digest = digest
.iter()
.map(|byte| format!("{byte:02x}"))View on GitHub (pinned to 0c42157ee5)
Solutions
- Trim the id once at its origin (when read from input or a file) and store the trimmed form.
- When accepting ids from users, normalize with trim() before any store call.
- Audit concatenation sites like format!("{a}-{b}") where either part may carry whitespace.
Example fix
// before let id = line_reader.read_line()?; // "turn-1\n" store.load_turn(&id)?; // bails: leading/trailing whitespace // after let id = line_reader.read_line()?.trim().to_string(); store.load_turn(&id)?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: trim at the boundary, once, before any store call let id = raw_id.trim(); anyhow::ensure!(!id.is_empty(), "id cannot be empty"); store.list_turns_for_thread(id)?;
Prevention
- Trim ids when reading from files, env vars, or stdin (newlines are the usual culprit).
- Never build ids by concatenating untrimmed fragments.
- Store the trimmed form so lookups never need ad-hoc normalization.
When it happens
Trigger: Passing an id like " turn-1" or "turn-1\n" to store APIs (load_thread, list_turns_for_thread, persist_turn with a padded thread_id, etc.); ids read from files or environment variables that include a trailing newline.
Common situations: Ids assembled from file lines without trimming the newline; copy-paste into prompts adding a trailing space; ids built by concatenating user tokens with careless separators.
Related errors
- {label} cannot be empty
- {label} contains unsupported characters
- Invalid preallocated task id: expected task_<16hex>
- ${name} is unavailable in Workflow scripts: runs must be det
- context_window must be greater than 0
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/c4d1aab986e6e784.
Report an issue: GitHub.