That's because of implicit returns. Procedures will implicitly return the last statement. Try blocks (and most other blocks) will also return their last statement. Of course each branch has to return the same type, Nim is strictly typed after all. Combining this knowledge we can look at your snippets. The first snippet fails because only of the branches in the try statement has a return value. The error isn't great, but it tries to tell you that there is a value somewhere where one isn't expected. The second snippet works because now we're explicitly returning from the good path, no longer relying on the implicit return. The last snippet works because both branches now return the same type, and the try block can therefore be returned implicitly from the proc. Note that here you could have the echo statement in the except branch, just before the 2.
For more information I wrote this article a while back: <https://peterme.net/tips-and-tricks-with-implicit-return-in-nim.html>