What getValues actually hands you
SpreadsheetApp.getRange('A1:C4').getValues() returns a two-dimensional JavaScript array: an outer array of rows, each containing an inner array of cell values. Row 0 is your header, row 3 is your last data row. The shape is always [rowCount][colCount] for a well-formed rectangular range.
That 'well-formed' qualifier is where people get burned. If you built the source array yourself by pushing rows of uneven length — common when you're assembling data from an API or a reduce — the inner arrays can have different lengths. Apps Script's setValues call validates the destination range dimensions against every inner array before writing a single cell. One short row and the whole write fails with 'The number of columns in the data does not match the number of columns in the range.' The fix is to pad before you transpose, not after.