In terms of go-ethereum code, transaction errors can be grouped into (I made up the terminology) several categories by their effect on state transition.
- System errors: like database connection issues. These, understandably, lead to cancelling the whole state transition. Retry follows.
- Contract errors: like stack overflows or out of gas. These lead to reverting the transaction progress, still applying the gas fee and other post-processing, and proceeding with the next transactions.
- Consensus errors: like invalid transaction nonce or unsuccessful balance transfer (only the initial one; doesn't apply for any following nested "insufficient balance for transfer"). These errors lead to discarding the whole state transition and marking the block invalid.
The question is why category (3) needs to be so fatal that the whole block would be rendered invalid? Intuitively seems like those are still "client" errors that could be scoped to the individual transactions, allowing the others to be executed.