Sparse block matrices all wrong

SparseArray reacts different when lists of matrices appear on the right hand side of Rule for Band. In this case, it assembles the ArrayFlattened block matrix instead of the matrix of blocks and Band[{i,j}] refers to the positions in the final, assembled matrix, not to the position within the matrix of blocks. I have to admit that this is really counterintuitive.

sa[dim_] := With[{n = Length[dim]},
  SparseArray[{
    Band[{1, 1}] -> λ,
    Band[{dim[[1]] + 1, 1}] -> 
     Table[Table[ Indexed[M[k], {i, j}], {i, dim[[k + 1]]}, {j, dim[[k]]}], {k, n - 1}], 
    Band[{1, Total[Most[dim]] + 1}] -> 
     Table[Indexed[M[n], {i, j}], {i, dim[[1]]}, {j, dim[[n]]}]},
   {Total[dim], Total[dim]}
   ]
  ]
sa[{2, 3, 4}]

There is also the undocumented function SparseArray`SparseBlockMatrix in which you can use {i,j}-> ... for the block in the i-row and j-th column. But SparseArray`SparseBlockMatrix does not go well with Band. And it is undocumented, so one has to go mostly by trial and error.


An alternative way without using Band:

sA = Module[{dim = #, n = Length @ #, l = Array[\[FormalX], Length @ #], 
     lim = λ IdentityMatrix[Total @ #], mats},
 mats = Table[Indexed[M[k], {i, j}], {k, n}, {i, dim[[Mod[k + 1, n, 1]]]}, {j, dim[[k]]}];
 SparseArray[ArrayFlatten[RotateRight[DiagonalMatrix[l]] /. Thread[l -> mats]] + lim]] &;

Examples:

MatrixForm @ sA @ {2, 3, 4}

enter image description here

MatrixForm @ sA @ {2, 3, 4, 3}

enter image description here