Exception classes and error handling

Because pwned-passwords-django communicates with a remote API, it can encounter problems, such as connection failures, connection timeouts, failures of the Pwned Passwords API, and so on.

Exceptions raised in communicating with Pwned Passwords will be caught and translated into instances of:

exception pwned_passwords_django.exceptions.PwnedPasswordsError[source]

A wrapper for all exceptions raised in communicating with Pwned Passwords.

Has the following attributes:

message

A message (str) describing the error.

code

A short code indicating the type of error.

params

A dict of additional information about the situation – such as the returned status code, or the timeout threshold, or attributes of the attempted request – for debugging purposes.

The code attribute uses the following enum:

class pwned_passwords_django.exceptions.ErrorCode[source]
API_TIMEOUT

An HTTP request to the Pwned Passwords API timed out.

HTTP_ERROR

An HTTP request to the Pwned Passwords API returned an error (4XX or 5XX) status code.

REQUEST_ERROR

Another type of error occurred in performing the request to the Pwned Passwords API.

UNKNOWN_ERROR

An unanticipated or unknown type of error occurred, possibly in code in pwned-passwords-django. This can happen if, for example, the Pwned Passwords API begins returning responses in a different format than expected and so parsing of the response fails.

How errors are handled

When the PwnedPasswords client class encounters a situation that requires raising a PwnedPasswordsError, it will emit a log message of log level logging.ERROR prior to raising the exception. It will also raise the exception “from” the parent exception it encountered, such as an httpx.TimeoutException or httpx.HttpStatusError. If you are working directly with an instance of PwnedPasswords or a customized subclass of it, your code is responsible for catching and handling any PwnedPasswordsError it raises.

When other parts of pwned-passwords-django encounter a PwnedPasswordsError raised from the client, they will behave as follows:

Filtering sensitive information

Because pwned-passwords-django works with values that are (or, in the case of the middleware, are likely to be) passwords or password-like credentials, care must be taken to avoid accidentally exposing those values in their raw form. This can easily happen by accident, for example, if an exception occurs while trying to check a password, since the password will usually be a local variable of the stack frame where the exception was raised, and thus is available from inspecting the traceback. Or a password might accidentally find its way into the message of an exception.

Django provides some tools to filter sensitive information from error reports, and it is strongly recommended that if you write code which interacts with pwned-passwords-django directly – for example, via the API – you take care to use those tools.

Internally, pwned-passwords-django takes the following measures:

This approach can make debugging errors more difficult, but such difficulty is generally preferable to accidental exposure of passwords via error-reporting tools.