Exceptions¶
Structure¶
In blargh exceptions are used internally to end processing of each request that has to fail. In looks more or less like this:
class Internals:
def process_data(data):
if Internals.invalid_data(data):
raise SomeException(msg="invalid data")
return 200, {'result': 'success'}
class Api:
def make_request(data):
try:
processed_data = Internals.process_data(data)
return 200, processed_data
except SomeException as e:
return e.status, e.details
# and our final user call is processed
Api.make_request({'some': data})
Contents of blargh.exceptions
:
Error
ProgrammingError
ServerError
e500
TransactionConflictRetriable
ClientError
e400
FieldDoesNotExists
FieldIsReadonly
FieldUpdateForbidden
SearchForbidden
BadParamValue
BadFieldValue
e401
e404
e422
Briefly speaking:
- ProgrammingError indicates that probably blargh user did something wrong
- ClientError indicates that application user did something wrong, and its descendants are related to specific kinds of mistakes
- e500 is raised when we encounter unexpected internal errors, e.g. disconnected database
- TransactionConflictRetriable is raised when request fails, but can be repeated (and
Api.make_request
is called again). Its only raised by PGStorage and more detailed description is there.
Some of those exceptions are never raised by blargh, but could be raised by applications extening it.
List of error codes¶
Status | Code | Reason |
---|---|---|
400 | bad_request | Unknown client error. This could also be a generic database exception, with details containing more information (e.g. ‘ERROR: null value in column “id” violates not-null constraint’) |
400 | field_does_not_exists | User request references non-existent object field. |
400 | field_is_readonly | User tries to change a field he is not allowed to modify in a direct way. |
400 | field_update_forbidden | User tries to change a field he is not allowed to modify in any way. |
400 | search_forbidden | User attempted to filter results (probably GET) by a field that shouldn’t be used for filtering, e.g. by a Calc field or my multi retaltional field. |
400 | bad_param_value | User sent invalid value of some url parameter, e.g. negative depth , or invalid json for filter . |
400 | bad_field_value | User tries to set field to an invalid value, e.g. to set ‘one’ to Scalar field with type_=int |
401 | unauthorized | Missing authorization header |
404 | object_does_not_exist | Referenced object does not exists.
This code for e.g. call PATCH cookie/1 {'jar': 7}
might be returned both when cookie with id=1 is missing,
or for missing jar with id=7 . |
422 | unprocessable_entity | (this currently never happens) |
500 | unknown_error | We have no idea what failed. Probably an unexpected programming error. |
500 | server_error | Something failed internally, e.g. could not connect to the database. |
Exception interface¶
from blargh.exceptions import Error
try:
raise Error(msg='something failed', what='no idea', where='also no idea')
except Error as e:
print(e.status) # 500
print(e.code) # 'unknown_error'
print(e.details) # {'msg': 'something failed',
# 'what': 'no idea',
# 'where': 'also no idea'}
# this is by default returned as response body when request fails
print(e.ext_data) # {'error': {'code': 'unknown_error',
# 'details': {'msg': 'something failed',
# 'what': 'no idea',
# 'where': 'also no idea'}