AFAIK, this should work, but instead I get the error from the inner catch, Cannot run statement, because transaction has already been successfully closed. What's the problem?
Which is actually more straightforward-looking, but it wasn't clear to me that the driver serializes the actual application of .run calls within the transaction. When looking at that code it looks like there's a possible race condition there because MATCH may execute before CREATE has completed. However in practice it seems that there is no such race condition. I'm not sure if that's a property of the JS event loop itself, or something that is explicitly enforced by the driver (or the backend) using locks.
And lastly (I know you've already solved it... but always fun to have options!) in this case you could just do it all in one query: CREATE (p:Person {id: 1}) RETURN p