Element.innerHTML and XSS Payloads

A while ago I was doing a security review of a web application, I came across a piece of JavaScript code. It was obviously vulnerable, I could trigger the vulnerability with a typical <img> payload, but not with the classic <script> type. I wondered why, and started digging deeper.

The vulnerable JavaScript code I was talking was something like this (changed a bit for easier reading):

var currentSearch = document.location.search;
var searchParams = new URLSearchParams(currentSearch);
var lang = searchParams.get('lang');
if (lang != null) {
 document.getElementById('ls').innerHTML = lang;
}

Lots of bad practices here, anyway, the lang parameter is vulnerable, it’s left here completely defenseless and naked.
So I tested it using a classic payload: <script>alert(1)</script> and it didn’t work! but why?!
I changed the payload to <img src=x onerror=alert(1)> and it triggered the XSS vulnerability.
Looking at the code I figured it out there must be something about either how this code reads and stores values OR the way it outputs the previously read values. Or both.
The first theory was rejected in 3 seconds, if there was a problem in the read & store part, things like encoding & filtering, it should have also affected the second payload, after all both of these payloads have some characters in common: <, > & alert(1).
Then it should be the output part.
I jumped into the documentation of innerHTML and there it was!\

HTML5 specifies that a <script> tag inserted with innerHTML should not execute.

A few lines below, it also states:

However, there are ways to execute JavaScript without using <script> elements, so there is still a security risk whenever you use innerHTML to set strings over which you have no control.

It also uses <img src='x' onerror='alert(1)'> as an example of this how restriction can be bypassed.
Amazing!