Maintainer of the W3C HTML Checker (validator) here.
The fix: put the script contents into a separate file and use the src attribute to reference that.
The checker reports an error for the snippet in the question because the HTML spec used to explicitly state that the script can’t have a defer attribute unless it also has a src attribute.
The spec no longer explicitly states that restriction, but I think that’s just an unintentional regression caused by a later spec change (which your question helped to catch—so, thanks!).
So I’ll investigate and raise a pull request for the spec fix and then update this answer later.
2018-05-05 update
For the record here, I did end up filing a pull request with an HTML spec patch:
https://github.com/whatwg/html/pull/2509
…and that was merged into the HTML spec source:
https://github.com/whatwg/html/commit/3c5180a08f90a375c64f8191f32f8c7ddfec0ba3
…and so now the current HTML spec once again states the restriction:
https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer
The async and defer attributes are boolean attributes that indicate how the script should be evaluated. Classic scripts may specify defer or async, but must not specify either unless the src attribute is present.