This might end up looking worse, but have you tried encoding these invariants into an ADT? It'd be nice to have an API that is impossible to get wrong.