You're not doing anything wrong. With a LazyVStack, the rows you insert above haven't been measured yet, so SwiftUI has to restore the position by guessing, and on iOS 27 that guess seems to land on the new page instead. That's also why the plain VStack works.
Since reaching into the UIScrollView was the only thing that worked for you, I'd lean on UIKit underneath rather than fight it. I hit the same problem and wrote a small package for it, Steady (I'm the author): https://github.com/RunTerror/Steady
It places older messages above what's on screen without ever moving it, so there's nothing to restore, and it opens at the newest message reliably. It works from SwiftUI through UIViewControllerRepresentable, and the repo has an example. The one catch is that you provide row heights yourself.
Happy to help if you try it.
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: