TL;DR
setValues() demands a 2D array โ an array of arrays. Pass a flat 1D array like [1, 2, 3] and you get this error. The fix is one extra set of brackets: [[1, 2, 3]] for a single row, or [[1], [2], [3]] for a single column.
// โ Wrong โ 1D array
range.setValues([1, 2, 3]);
// โ
Correct โ 2D array (one row)
range.setValues([[1, 2, 3]]);
// โ
Correct โ 2D array (one column)
range.setValues([[1], [2], [3]]);
Root Cause
In the Apps Script execution log, the full error reads:
Exception: The parameters (number[]) don't match the method signature for SpreadsheetApp.Range.setValues.
Spreadsheets are grids. Rows and columns. setValues() maps directly onto that structure, so it always expects a 2D array:
- The outer array = rows.
- Each inner array = the cells in that row.
Pass [10, 20, 30] and Apps Script sees a number[] โ one-dimensional. It needs number[][]. The signature doesn't match, so the method throws before writing a single byte.
The type in parentheses shifts based on your data โ you might see (number[]), (string[]), or (String[]). Doesn't matter. The fix is always the same: wrap it in another array.
Common Scenarios and Fixes
Scenario 1: Writing a single row of values
Say you have three values โ a name, an age, and a job title โ and want to drop them into row 1.
// โ Broken
function writeRow() {
var sheet = SpreadsheetApp.getActiveSheet();
var values = ["Alice", 30, "Engineer"];
sheet.getRange(1, 1, 1, 3).setValues(values); // TypeError!
}
// โ
Fixed
function writeRow() {
var sheet = SpreadsheetApp.getActiveSheet();
var values = [["Alice", 30, "Engineer"]];
sheet.getRange(1, 1, 1, 3).setValues(values);
}
getRange(1, 1, 1, 3) means 1 row ร 3 columns. Your 2D array must match: one inner array containing exactly 3 elements.
Scenario 2: Writing a single column of values
Going down a column is the reverse shape โ each value gets its own inner array.
// โ Broken
function writeColumn() {
var sheet = SpreadsheetApp.getActiveSheet();
var values = [100, 200, 300];
sheet.getRange(1, 1, 3, 1).setValues(values); // TypeError!
}
// โ
Fixed โ each value lives in its own row array
function writeColumn() {
var sheet = SpreadsheetApp.getActiveSheet();
var values = [[100], [200], [300]];
sheet.getRange(1, 1, 3, 1).setValues(values);
}
Scenario 3: Building the array dynamically in a loop
Loop-built arrays are the most common place this bug hides. You iterate over data, push values, and forget each push needs to be a row โ not a bare value.
// โ Broken โ pushes flat numbers
function processData() {
var sheet = SpreadsheetApp.getActiveSheet();
var output = [];
var data = [10, 20, 30, 40];
data.forEach(function(val) {
output.push(val * 2); // pushing a number, not an array
});
sheet.getRange(1, 1, output.length, 1).setValues(output); // TypeError!
}
// โ
Fixed โ push a mini-array each iteration
function processData() {
var sheet = SpreadsheetApp.getActiveSheet();
var output = [];
var data = [10, 20, 30, 40];
data.forEach(function(val) {
output.push([val * 2]); // each row is its own array
});
sheet.getRange(1, 1, output.length, 1).setValues(output);
}
Scenario 4: Accidentally flattening getValues() output
getValues() always returns a 2D array โ that part is safe. The trouble starts when you call .flat(), chain a .map() that returns primitives, or slice a single-row result. Any of those can silently strip the outer array.
// โ Broken โ .flat() kills the 2D structure
function copyRow() {
var sheet = SpreadsheetApp.getActiveSheet();
var sourceValues = sheet.getRange("A1:C1").getValues().flat();
// sourceValues is now ["x", "y", "z"] โ 1D!
sheet.getRange("A2:C2").setValues(sourceValues); // TypeError!
}
// โ
Fixed โ use getValues() result directly
function copyRow() {
var sheet = SpreadsheetApp.getActiveSheet();
var sourceValues = sheet.getRange("A1:C1").getValues();
// sourceValues is [["x", "y", "z"]] โ still 2D
sheet.getRange("A2:C2").setValues(sourceValues);
}
Scenario 5: Writing a single cell
Single-cell writes have a cleaner option. setValue() (no 's') takes a plain value. If you insist on setValues(), you still need the double brackets.
// Option A โ cleaner for one cell
sheet.getRange("A1").setValue(42);
// Option B โ setValues() still needs 2D
sheet.getRange("A1").setValues([[42]]);
Debugging Checklist
Not sure what shape your array is? Log it before the call:
var values = buildMyArray(); // whatever your logic is
Logger.log(JSON.stringify(values));
Logger.log("Is array: " + Array.isArray(values));
Logger.log("Is 2D: " + Array.isArray(values[0]));
var numRows = values.length;
var numCols = values[0].length;
Logger.log("Dimensions: " + numRows + " rows x " + numCols + " cols");
// Then confirm the range matches those dimensions
sheet.getRange(startRow, startCol, numRows, numCols).setValues(values);
Range dimensions must match exactly. A 3ร2 array needs a 3-row, 2-column range. Size mismatches throw a different error โ but getting the 2D structure right first eliminates this specific one.
Verify the Fix
- Open the script editor: Extensions โ Apps Script inside your spreadsheet.
- Run your function with the โถ button or Ctrl+R.
- Check the Execution log (View โ Logs) โ no exceptions means the call succeeded.
- Flip back to the spreadsheet and confirm the target cells hold the right values.
Quick Reference
- Single row, multiple columns:
[[val1, val2, val3]] - Multiple rows, single column:
[[val1], [val2], [val3]] - Multiple rows, multiple columns:
[[a1, b1], [a2, b2], [a3, b3]] - Single cell via setValues:
[[val]] - Single cell shortcut:
setValue(val)โ no brackets needed

