Can I return an error from anvil.server.connect()?

When I call anvil.server.connect(), is it correct to say that whether it succeeds or fails, it does not return anything?

For instance, if I call it in a script and pass it the wrong uplink key, it will print error messages to the terminal like

Connecting to ws://localhost:3030/_/uplink
Anvil websocket open
Fatal error from Anvil server: Incorrect uplink key
Anvil websocket closed (code 1000, reason=b'')
Reconnecting Anvil Uplink...
Connecting to ws://localhost:3030/_/uplink
Anvil websocket open
Fatal error from Anvil server: Incorrect uplink key
Anvil websocket closed (code 1000, reason=b'')
Reconnecting Anvil Uplink...
Connecting to ws://localhost:3030/_/uplink
Anvil websocket open
Fatal error from Anvil server: Incorrect uplink key
Anvil websocket closed (code 1000, reason=b'')
Reconnecting Anvil Uplink...

and it seems to do this forever, I think.

If Iā€™m making the connection inside a script, I would prefer anvil.server.connect() to make a few attempts and then raise an exception so that I can fail gracefully. In particular, if the connection is failing for a reason that is unlikely to go away by itself (e.g. the uplink key is wrong!), an exception would be a nice behaviour.

At the moment, Iā€™m not sure how to get anvil.server.connect() to try to connect for only a finite amount of time, or the best way to tell whether or not the connection has succeeded. Is there a good way?

Thanks!

1 Like

Hi there! Yes, you arenā€™t missing anything - that behaviour is whatā€™s expected at the moment - it will continue to retry forever in the background.

There is a handy way to check your connection from a local script: use anvil.server.call(...). If that fails, it will throw an exception that tells you if thereā€™s a connection problem.

import anvil.server

try:
    anvil.server.connect("Not an uplink key")
    anvil.server.call("some_function_in_your_server")
except Exception as e:
    print("Problem connecting: %s" % e)
    print("caught an exception, now we can handle the problem in here")

which prints

Problem connecting: Anvil fatal error: Incorrect uplink key
caught an exception, now we can handle the problem in here

Iā€™ve added a feature request to improve anvil.server.connect() in the way you suggest. As a user on a Support contract you can ask us to prioritise certain features for you, so if this behaviour of anvil.server.connect is particularly getting in your way let me know and we can make improving it a priority.

1 Like

If so, then how could it ever get to the anvil.server.call line in your example?

Edit: ā€œā€¦in the backgroundā€¦ā€ So the connect attempt returns, regardless of whether it succeeded or failed. And it keeps trying in the background. So that failure could turn into a success at any time, without notice. Got it.

I had previously assumed that it returned only on success, and raised an exception on failure.

Thanks @hannah! Should I also add a little delay (like time.sleep(0.2)) before the server call, to allow time for the connection to complete?

Try and fail is actually a pretty pythonic way to do it, I guess the main drawback of the current situation is the code canā€™t access the details of the error and find out that it was ā€˜incorrect uplink keyā€™.

Re support contract - thank you :slight_smile: This particular issue isnā€™t a major one for us right now as the uplink is being called in a command-line tool that can terminate if there are issues, and can print to the terminal. It was mostly me wondering if I should be writing my scripts in a better way.

Should I also add a little delay (like time.sleep(0.2) ) before the server call, to allow time for the connection to complete?

No need for that! When you call anvil.server.call(), it will wait for the connection to complete (or fail) before making the call.

Iā€™m having trouble reconciling these two statements.

Edit: if it waits until it succeeds, then how could the immediately following anvil.server.call() fail with a connection problem?

Youā€™re right; I have updated the previous comment to read ā€œit will wait for the connection to complete (or fail)ā€¦ā€.

This is, by the way, the reason that anvil.server.call()ing something is the answer to @claresloggettā€™s question. Just calling anvil.server.connect() doesnā€™t block her code ā€“ it just kicks off a connection in the background, and itā€™s not a problem if that connection hasnā€™t succeeded yet.

However, when you make an anvil.server.call(), we obviously need a working connection to do that, so that function waits until the connection either succeeds (in which case it makes the call, then blocks until it gets a response) or fails (in which case it throws an exception because it canā€™t make the call).

Does that explain it?

1 Like

Yes, thank you!

Edit: In fact, that explains a recent Exception in one of my programs. Now I have a good way to understand it. And deal with it. Much appreciated.

1 Like