You're right that a race condition could lead to the same or similar other issues.
Your original 100sats were represented by ^2 set of proofs (ecash notes) at the beginning - 64,32,4. To get 1sat, (let's ignore fee reserve for simplicity) wallet takes 64 proof and swaps it with the mint for 32,16,8,1,1 and uses 1sat proof to settle payment.
For lightning fee reserve, mint retutns unused fees as a fresh ecash back to wallet.
So plenty room to race inside the wallet state or get out of sync with the mint in case of parallel/async processes.
Minibits internally uses synchronous queue for all ecash ops to prevent that + locks during network requests (so it can e.g. recover back sent ecash when mint response won't come at all).
Even technically prevented, I still might have some logical issue leading to race condition but was not so far able to pin it. As it happens much more often with nwc, background procesessing is suspicious to me as well.
Will repeat your exact 20x1sat zaps test case on dev device.