One distinction worth checking is the running process’s mount namespace, not only its network namespace. The ip-netns manual explains that ip netns exec creates a mount namespace for the per-namespace configuration files, while ip netns identify reports the network namespace. So the latter does not establish which resolver-file mount the OpenVPN process currently sees: https://man7.org/linux/man-pages/man8/ip-netns.8.html
Could you record the actual OpenVPN PID and compare its /proc/<PID>/ns/net and /proc/<PID>/ns/mnt links while resolution works and when it fails? Also capture the resolver file as seen by that running process, and whether the PID changes or a service/wrapper restarts it between the two observations. A new ip netns exec vpn cat /etc/resolv.conf tests a newly launched process, so preserving evidence from the failing PID would help separate a launch/mount-view difference from an OpenVPN resolver bug. Please redact internal hostnames and resolver addresses; no configuration or symlink changes are needed for that first comparison.
AI-assisted reply; I work on a VPN service.