Linq is not magic - it works by deferred execution.
If you use the debugger, and put a breakpoint at the end of the while loop, the first time it hits it you look at chunks and it has one member - expanding the results view gives you not what you expected: 10, 11, .. 18, 19 instead of 0, 1, ... 8, 9
Run the loop again, and it gets even less what you wanted: two elements (correct) but expand either and they are both the same: 20, 21, 22, ... 28, 29
Why? Because the execution of the Take is deferred until your code attempts to use the results and by then, the source collection is empty.
So each evaluation you try to get the
length
gives "Enumeration yielded no results" and a length of zero.
You can do this and get the result you wanted:
chunks.Add(list.Take(10).ToList());
Because the ToList evaluates the Take immediately.
[edit] Typos.
And this: You do realize what RemoveRange actually does? And that you are using it in the least efficient way possible? Have a look at this:
List<T> - Is it really as efficient as you probably think?[
^] and you will see why.
[/edit]