Help me understand why hairpin NAT rule didn't work but workaround did

I wasn’t able to make requests against my public IP but eventually remembered I had to enable reverse NAT. I followed the official documentation and added a src-nat rule:

 4    ;;; HAIRPIN NAT
      chain=srcnat action=masquerade to-addresses=192.168.88.10 protocol=tcp src-address=192.168.88.0/24 dst-address=192.168.88.10 log=no log-prefix=""

Unfortunately, I was still unable to make requests that resolve to my public IP but adding the rule below fixed it:

 6    ;;; ;; Workaround for non-functioning hairpin NAT rule
      chain=dstnat action=dst-nat to-addresses=192.168.88.10 protocol=tcp dst-address=69.69.69.69 log=no log-prefix=""

(69.69.69.69 refers to my public IP)

Why didn’t the former rule work? Am I likely to experience any weirdness using this setup?

Some context. After attempting to create a separate subnet for my server, somehow botching it and losing Internet access, I ended up fully resetting the router. I have added only four port-forwarding settings and everything else is default. My machines are connected to a switch and this in turn is connected to the router, which is connected to my ISP’s (cable) router.

Because dst-address property is a matcher … and rule only acts if all the matchers match. And you likely used your public IP address when checking hairpin NAT.

As to the rest of rule: if action is masquerade, then setting property to-addresses is not needed (masquerade takes the most appropriate router’s address when substituting original src-address instead).