aaif-goose/goose · error
Range start must not follow range end
Error message
Range start must not follow range end
What it means
validate_range_bounds() rejects ranges whose start corner comes after the end corner: start_row > end_row or start_col > end_col bails with 'Range start must not follow range end'. Both corners are otherwise valid cells; only their order is wrong. Reversing the two references fixes it.
Source
Thrown at crates/goose-mcp/src/computercontroller/xlsx_tool.rs:240
// parse_cell_reference returns (row, col), so start.0 is row, start.1 is col
Ok((start.0, start.1, end.0, end.1))
}
fn validate_range_bounds(
start_row: u32,
start_col: u32,
end_row: u32,
end_col: u32,
) -> Result<(u32, u32)> {
anyhow::ensure!(
(1..=MAX_EXCEL_ROWS).contains(&start_row) && (1..=MAX_EXCEL_ROWS).contains(&end_row),
"Row must be between 1 and {MAX_EXCEL_ROWS}"
);
anyhow::ensure!(
(1..=MAX_EXCEL_COLUMNS).contains(&start_col) && (1..=MAX_EXCEL_COLUMNS).contains(&end_col),
"Column must be between 1 and {MAX_EXCEL_COLUMNS}"
);
anyhow::ensure!(
start_row <= end_row && start_col <= end_col,
"Range start must not follow range end"
);
let row_count = end_row
.checked_sub(start_row)
.and_then(|span| span.checked_add(1))
.context("Row span overflow")?;
let column_count = end_col
.checked_sub(start_col)
.and_then(|span| span.checked_add(1))
.context("Column span overflow")?;
let cell_count = u64::from(row_count)
.checked_mul(u64::from(column_count))
.context("Range area overflow")?;
anyhow::ensure!(
cell_count <= MAX_RANGE_CELLS,
"Range contains {cell_count} cells; maximum is {MAX_RANGE_CELLS}"View on GitHub (pinned to 3810898a74)
Solutions
- Write the upper-left cell first: 'A1:B2', not 'B2:A1'.
- When building from two arbitrary corners, sort rows and columns (min start, max end) before formatting.
- Validate ordering client-side with a small helper before calling the tool.
Example fix
// before
let range = format!("{}:{}", bottom_right, top_left); // "B2:A1" -> error
// after: normalize corner order before formatting
let (r1, r2) = (top_left_row.min(bottom_row), top_left_row.max(bottom_row));
let (c1, c2) = (left_col.min(right_col), left_col.max(right_col));
let range = format!("{}{}:{}{}", col_name(c1), r1, col_name(c2), r2); Defensive patterns
Strategy: validation
Validate before calling
fn normalize_corners(r1: u32, c1: u32, r2: u32, c2: u32) -> (u32, u32, u32, u32) {
(r1.min(r2), c1.min(c2), r1.max(r2), c1.max(c2))
}
// build the range string from normalized (min, max) corners
let (sr, sc, er, ec) = normalize_corners(sr, sc, er, ec);
let range = format!("{}{}:{}{}", col_name(sc), sr, col_name(ec), er); Type guard
fn is_ordered_range(range: &str) -> bool {
let cells: Vec<&str> = range.split(':').collect();
if cells.len() != 2 { return false; }
let parse = |c: &str| (
c.chars().filter(|x| x.is_ascii_alphabetic()).count(),
c.chars().filter(|x| x.is_ascii_digit()).count(),
);
// full ordering check needs numeric conversion; use parse_range-style logic
true // placeholder — prefer normalizing corners over checking order
} Prevention
- Always emit the upper-left corner first (smallest row and column).
- Normalize arbitrary corners with min/max before formatting the range.
- Remember Excel ranges are always top-left:bottom-right.
When it happens
Trigger: Ranges like 'B2:A1' (both reversed), 'A5:A1' (rows reversed), or 'C1:A1' (columns reversed). Typically produced by computing start/end independently (e.g. min/max swapped) when constructing the range string.
Common situations: Agents stringing together cell coordinates without sorting; drag-selection processed in reverse; user typing the bottom-right cell first; rectangle math using unordered corners.
Related errors
- Invalid range format. Expected format: 'A1:B10'
- Row must be between 1 and {MAX_EXCEL_ROWS}
- Column must be between 1 and {MAX_EXCEL_COLUMNS}
- Range contains {cell_count} cells; maximum is {MAX_RANGE_CEL
- Invalid model spec '{}': expected format 'user/repo:quantiza
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/dac6ad66da2cf865.
Report an issue: GitHub.