aaif-goose/goose · error
Invalid range format. Expected format: 'A1:B10'
Error message
Invalid range format. Expected format: 'A1:B10'
What it means
parse_range() in the computercontroller xlsx tool requires a range of exactly two colon-separated cell references, 'A1:B10'. Splitting on ':' must yield exactly 2 parts or it bails with this message. The two halves are then parsed by parse_cell_reference (letters then digits, e.g. 'B10'); malformed halves raise their own errors.
Source
Thrown at crates/goose-mcp/src/computercontroller/xlsx_tool.rs:216
pub fn get_cell_value(&self, worksheet: &Worksheet, row: u32, col: u32) -> Result<CellValue> {
let cell = worksheet.cell((col, row)).context("Cell not found")?;
Ok(CellValue {
value: cell.value().into_owned(),
formula: if cell.formula().is_empty() {
None
} else {
Some(cell.formula().to_string())
},
})
}
}
fn parse_range(range: &str) -> Result<(u32, u32, u32, u32)> {
// Handle ranges like "A1:B10" and return (start_row, start_col, end_row, end_col)
let parts: Vec<&str> = range.split(':').collect();
if parts.len() != 2 {
anyhow::bail!("Invalid range format. Expected format: 'A1:B10'");
}
let start = parse_cell_reference(parts[0])?;
let end = parse_cell_reference(parts[1])?;
// 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}"View on GitHub (pinned to 3810898a74)
Solutions
- Pass a full range: 'A1:B10' format, exactly one colon.
- For a single cell, duplicate it: 'A1:A1'.
- Trim whitespace and uppercase the string before calling the tool.
- Have the agent validate the range with a regex before invoking the tool.
Example fix
// before let data = spreadsheet.get_range(&ws, "A1")?; // -> Invalid range format // after let data = spreadsheet.get_range(&ws, "A1:A1")?;
Defensive patterns
Strategy: validation
Validate before calling
fn normalize_range(range: &str) -> String {
let r = range.trim().to_uppercase();
if r.contains(':') { r } else { format!("{r}:{r}") } // single cell -> A1:A1
}
let range = normalize_range(raw);
anyhow::ensure!(range.matches(':').count() == 1, "range must look like 'A1:B10'"); Type guard
fn is_valid_excel_range_format(range: &str) -> bool {
let re = regex::Regex::new(
r"^[A-Za-z]{1,3}[1-9][0-9]{0,6}:[A-Za-z]{1,3}[1-9][0-9]{0,6}$"
).unwrap();
re.is_match(range.trim())
} Prevention
- Always send two colon-separated corners, even for a single cell ('A1:A1').
- Trim and uppercase the range before calling the tool.
- Have agents run the regex guard before emitting a tool call.
When it happens
Trigger: Calling the spreadsheet read/range tool with 'A1' (single cell, no colon), 'A1:B2:C3' (two colons), '' or ':' (empty parts), or 'A1 :' with spaces. Any get_range() call funnels through parse_range first.
Common situations: LLM agents constructing the range string and omitting the colon; users copying a single-cell address from Excel's name box; localized Excel installs using a different separator; trailing whitespace not trimmed.
Related errors
- Row must be between 1 and {MAX_EXCEL_ROWS}
- Column must be between 1 and {MAX_EXCEL_COLUMNS}
- Range start must not follow range end
- 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/51a3540dc4f9cb85.
Report an issue: GitHub.