Thanks for the sample project, it made this easy to reproduce.
This is a bug, and your hunch about the returned row number was close to the cause. When a ListBox has an active sort, a row added afterwards appears on screen in its sorted position, but SelectedRowIndex was reporting that on-screen position instead of the row number used by RowTag and the other row methods. The tag itself was stored on the correct row; it was the read-back that mixed up the numbering, so RowTag(SelectedRowIndex) returned a different row's tag.
I've fixed this for the next release. SelectedRowIndex now uses the same row numbering as every other row method, both when reading it and when setting it, so your project now behaves exactly as written, including the SelectionChanged handler: https://feedback.objo.dev/bug/1715
On 26.10.1 you can work around it with the method form of SelectedRowIndex, which already returns the correct row number:
If Me.SelectedRowIndex = -1 Then Return
Label1.Text = Me.RowTag(Me.SelectedRowIndex(0)).ToString()