Why the error fires
setValues takes a 2-D array and writes it into a Range object. The API requires an exact match: the Range must have the same number of rows and the same number of columns as the array. If either dimension is off by even one, you get the 'number of rows in the data does not match' error (sometimes a column variant surfaces instead, but the root cause is identical).
The mismatch almost always comes from a hard-coded getRange call written when the script was first drafted against a known dataset, combined with an array that is later built dynamically — filtered with a condition, grown with push, or sliced. The range stays fixed; the array changes with the data. At some row count they diverge and the script breaks.
The first time I hit this, I spent twenty minutes re-checking my filter logic when the actual problem was a getRange('A1:D50') I'd forgotten at the bottom of the function. The data had shrunk to 31 rows; the range expected 50.