snowflakedb / snowflakedb/snowflake-connector-python

SNOW-897499: Throw `ReauthenticationRequest` error instead of `ProgrammingError`

Open
#1,705 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature status-triage_done
Dominant language
Python
Stars
730
Forks
574
Avg merge
5h 45m
Merged PRs (30d)
16

Description

What is the current behavior?

Currently if ReauthenticationRequest gets raised, it gets caught by the library and instead ProgrammingError gets raised.
network.py

except ReauthenticationRequest as ex:
    if self._connection._authenticator != EXTERNAL_BROWSER_AUTHENTICATOR:
        raise ex.cause
    ret = self._connection._reauthenticate()

Both errors would be captured in logs, but there's no way to determine in code if the error is caused by reauthentication request.

What is the desired behavior?

Desired behaviour is either raising ProgrammingError but like this: raise ex.cause from ex. Or throw ReauthenticationRequest error instead.

How would this improve snowflake-connector-python?

This would allow users to catch ReauthenticationRequest separately from ProgrammingError and have a different logic to handle one or the other.

References and other background

I have this code for running queries in Snowflake.

try:
    snowflake.execute(query)
except (snowflake.connector.InterfaceError,
        snowflake.connector.OperationalError) as exc: # these errors can be handled by recreating connection
    logging.error(exc)
    snowflake.recreate_connection()
    snowflake.execute(query)

But unfortunately this code fails when ProgrammingError gets raised. I can see that most of the times ProgrammingError gets raised in situations when recreating connection would not help. However, it's not the case when it gets raised because of ReauthenticationRequest. To handle this I need to do the following:

try:
    snowflake.execute(query)
except (snowflake.connector.InterfaceError,
        snowflake.connector.OperationalError,
        snowflake.connector.errors.ProgrammingError) as exc:
    if isinstance(snowflake.connector.errors.ProgrammingError, exc) and 'Authentication token has expired' not in exc.msg:
        raise
    logging.error(exc)
    snowflake.recreate_connection()
    snowflake.execute(query)

This code is not very stable because it relies on the message in the error.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/snowflake/connector/network.py around the ReauthenticationRequest handler at line 697, then trace how its cause becomes a ProgrammingError. Determine the intended exception and chaining behavior from the issue requirements, and verify that callers can distinguish reauthentication failures without parsing the error message.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authentication, database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.