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

  1. Trim the id once at its origin (when read from input or a file) and store the trimmed form.
  2. When accepting ids from users, normalize with trim() before any store call.
  3. 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

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


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/c4d1aab986e6e784. Report an issue: GitHub.