Although it is not easy to debug a script where conditions change at each run because of randomness (I haven't took the time to change it though), I found the root cause and I will open a bug in the tracker.
When a station (let's call it AP1) successfully receives a MPDU from an A-MPDU (from STA 1), but in the meantime other A-MPDU transmissions occur (from STA 2 to AP2), we observe collisions and MacLow::ReceiveError is triggered for each reception.
It is important to note that MacLow::ReceiveError is triggered at AP1 also for packets sent by STA2 (if packet is corrupted, they may not decode the originator!).
But since AP1 received at least one MPDU, it will enter this condition "if (isInAmpdu && m_receivedAtLeastOneMpdu && (ampdu.GetNoOfMpdus () == 1))" when the last MPDU from the A-MPDU sent from STA2 is received by AP1 (if last MPDU from STA1 is received before = no problem, that's why in some cases simulation does not fail...). Based on that, AP1 will (wrongly!) send a BACK to STA2. This comes from this call:
NS_LOG_DEBUG ("last a-mpdu subframe detected/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
m_sendAckEvent = Simulator::Schedule (GetSifs (),
&MacLow::SendBlockAckAfterAmpdu, this,
hdr.GetQosTid (),
hdr.GetAddr2 (),
hdr.GetDuration (),
m_currentTxVector);
Of course, since no agreement exists between STA2 and AP1, this triggers the corresponding assert.
Is it a bit clearer or not?
I do not solve it directly but I will open a bug in the tracker, because I want to find the most "elegant" way to fix it (I see multiple solutions for this, but I need to check for the best one.)
Thanks for reporting this.
Just one tip for future debugging: try to use the same failing scenario to reproduce a bug, avoid randomness for this (How will you know that your bug is fixed? Luck can be on your side for a large number of runs...)