From e0d39d1e082b6b1158c224c86ed49419c4a293ec Mon Sep 17 00:00:00 2001 From: sandikodev Date: Sat, 4 Apr 2026 23:53:15 +0700 Subject: [PATCH] fix(todo): improve validation error messages to help model self-correct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the model sends invalid todo_list parameters (duplicate indices, mismatched task/index counts, or out-of-bounds indices), the error messages were terse and lacked context needed for the model to retry correctly. Improve all three validation error messages: - 'Insertion indices must be unique' → clarifies each task needs a distinct index - 'Must provide an index for every new task' → shows actual counts (N tasks, M indices) - 'Index N is out of bounds' → shows valid range and current list size for all operations This helps the model understand exactly what correction is needed without requiring a full retry from scratch. Fixes #3184 --- crates/chat-cli/src/cli/chat/tools/todo.rs | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/chat-cli/src/cli/chat/tools/todo.rs b/crates/chat-cli/src/cli/chat/tools/todo.rs index 204657f270..e629141efc 100644 --- a/crates/chat-cli/src/cli/chat/tools/todo.rs +++ b/crates/chat-cli/src/cli/chat/tools/todo.rs @@ -414,7 +414,11 @@ impl TodoList { } for i in completed_indices.iter() { if *i >= state.tasks.len() { - bail!("Index {i} is out of bounds for length {}, ", state.tasks.len()); + bail!( + "Index {i} is out of bounds — valid indices are 0..{} (current list has {} tasks)", + state.tasks.len(), + state.tasks.len() + ); } } }, @@ -428,15 +432,23 @@ impl TodoList { if new_tasks.iter().any(|task| task.trim().is_empty()) { bail!("New tasks cannot be empty"); } else if has_duplicates(insert_indices) { - bail!("Insertion indices must be unique") + bail!("Insertion indices must be unique — each task must have a distinct index") } else if new_tasks.len() != insert_indices.len() { - bail!("Must provide an index for every new task"); + bail!( + "Must provide an index for every new task — got {} tasks but {} indices", + new_tasks.len(), + insert_indices.len() + ); } else if new_description.is_some() && new_description.as_ref().unwrap().trim().is_empty() { bail!("New description cannot be empty"); } for i in insert_indices.iter() { if *i > state.tasks.len() { - bail!("Index {i} is out of bounds for length {}, ", state.tasks.len()); + bail!( + "Index {i} is out of bounds — valid insertion indices are 0..={} (current list has {} tasks)", + state.tasks.len(), + state.tasks.len() + ); } } }, @@ -447,13 +459,17 @@ impl TodoList { } => { let state = TodoListState::load(os, id).await?; if has_duplicates(remove_indices) { - bail!("Removal indices must be unique") + bail!("Removal indices must be unique — each index must appear only once") } else if new_description.is_some() && new_description.as_ref().unwrap().trim().is_empty() { bail!("New description cannot be empty"); } for i in remove_indices.iter() { if *i >= state.tasks.len() { - bail!("Index {i} is out of bounds for length {}, ", state.tasks.len()); + bail!( + "Index {i} is out of bounds — valid indices are 0..{} (current list has {} tasks)", + state.tasks.len(), + state.tasks.len() + ); } } },