◆ valueAsNumber で取得すると NaN になるケースがある
◆ NaN を代入しようとするのが問題

なんか reportValidity で表示されるエラー通知が点滅してました
原因は setInterval で毎回上書きされていたことでした

これで再現できます

<!doctype html>
<script src="https://unpkg.com/hyperhtml@latest/min.js"></script>
<script>
const { bind } = hyperHTML
let time = 0
let num = 0

const render = () => {console.log(num)
bind(document.body)`
<div>time: ${time}</div>
<div>
<input id="n" type="number" required max=5 value=${num} onchange=${onChange}>
<button onclick=${eve => n.reportValidity()}>report validity</button>
</div>
<div>value of num: ${num}</div>
`
}

const onChange = eve => {
num = eve.target.valueAsNumber
render()
}

setInterval(() => {
time++
render()
}, 1000)
</script>

DEMO

input を空文字にして report validity ボタンを押してみてください
エラー出た後に 1 秒ごとに点滅します

通常 hyperHTML では必要箇所のみの書き換えなのでタイマー更新時に変更していない input の値は変わらないはずです
今回変わってしまっていたのは valueAsNumber を使ってるからです
このプロパティでは空文字のときは 0 でなく NaN が取得されます
実際の値は NaN とは異なるので毎回代入して一瞬変更されるためエラーが再表示されます
max は 5 としていますが 10 を入力してエラーを出した場合は数値が取得できているので点滅しません

num の更新時に valueAsNumber || 0 にして NaN は 0 にするようにすれば点滅しなくなります
空文字は NaN にしておきたいという場合は render 時に 0 に置き換えてもいいです