I currently use Django for SaaS development, and I develop and maintain several SaaS applications at the same time. Many SaaS applications have agreed-upon error codes, some used to handle login state, others to mark business logic status. For a feature that is so strongly shared across projects, it is well worth spending time to study and research it. This post mainly discusses the purpose of error codes, how to design error codes, and how to use Django middleware to implement exception handling and the return of error codes.
1. The Purpose of Error Codes
Error codes are a set of numbers or letters associated with error information, used to agree on error states.
In a web application, a single API access involves reverse proxy forwarding, business logic processing, database access, template rendering, middleware processing, and other stages, so all kinds of errors are unavoidable. At the same time, the more complex the system, the longer the access path and the more modules there are, the higher the probability of errors.
Since errors cannot be avoided, the error information has to be reported back. Returning error information serves two purposes: on one hand, during the application development stage it makes debugging easier, allows adding the corresponding logic, and lets you prompt the user; on the other hand, when the application is running there may be potential exception risks, and error codes can assist in locating and fixing problems.
HTTP status codes are the most common — an agreed-upon set of codes for handling service state. An HTTP status code usually consists of three digits; the first digit defines the category of the response, and there are only five possible values.
| Status Code | Range | Meaning |
|---|---|---|
| 1xx | 100-101 | Informational – the request has been received, continue processing |
| 2xx | 200-206 | Success – the request has been successfully received, understood, accepted |
| 3xx | 300-305 | Redirection – the information is incomplete and needs to be supplemented further |
| 4xx | 400-415 | Client error – the request has a syntax error or cannot be fulfilled |
| 5xx | 500-505 | Server error – the server failed to fulfill a legitimate request |
It is worth noting that HTTP status codes can be extended with a decimal to describe the server state in more detail; for example, 403 means access forbidden, 403.1 means executable access forbidden, and 403.2 means read access forbidden.
Through HTTP status codes, the client can effectively learn the response state of the server, better handle exceptional situations, and prompt the user with information. Error codes and HTTP status codes are similar in spirit; the difference is that error codes agree on business logic, while HTTP status codes agree on the server’s response state.
In the communication process of a web application, if the HTTP status code is not enough to express the server’s response state, an error code can supplement it; for example, the server returns {'code': 500101, 'message': u'连接数据库错误'}. The HTTP status code is a convention that has already reached consensus, whereas an error code requires a new convention to be established. In business logic, an HTTP status code can also express a business error state, for example using 412 to indicate that a precondition was not met. Error codes and HTTP status codes overlap, but they cannot replace each other.
2. How to Design Error Codes
2.1 Error Codes of Some Public Platforms
Error codes fall mainly into two categories
(1) Codes below 100, indicating that the user request does not pass basic validation, for example field validation, permissions, frequency, etc.
(2) Sub-error codes starting with “isp.”, indicating server-side exceptions, such as “isp.remote-service-error”, “isp.remote-service-timeout”, etc. Different services use different prefixes.
There are also some specially agreed error codes, such as 801, 802, etc.
Error code description:
(1) ret = 0, correct return
(2) ret > 0, an error occurred when calling the OpenAPI, and the developer needs to handle it accordingly.
(3) -50 <= ret <= -1, the API call could not pass the validation of the API proxy machine, and the developer needs to handle it accordingly.
(4) ret <-50, internal system error
In addition, the SDKs in various languages provided by the Tencent Open Platform share the same error code meanings. Numbers are used, for example 1801, 1802, 1803, etc.
Mainly three-digit and four-digit numbers; below are some of the error codes:
| Error Code | Error Type | Description |
|---|---|---|
| 0 | Success | The call succeeded |
| 401< | HTTP request parameters do not meet requirements | HTTP request parameters do not meet requirements |
| 503 | Call quota exceeded | Call quota exceeded |
| 504 | Service failure | Service failure |
| 4000 | Invalid request parameters | A required parameter is missing, or the parameter value format is incorrect |
| 6000 | Internal server error | An error occurred inside the server, please retry later or contact customer service for help. |
The payment error codes of the Tencent Open Platform are expressed as three groups of numbers joined by hyphens. Judging from the letters of the error codes, hyphens separate different modules, or represent different processing stages, but the official documentation does not state this explicitly. Below are some of the error codes:
Error code: 1003-498493-106
Error code: 1003-498692-106
Error code: 1025-1025-0
Error code: 1043-10053-0
Error code: 1058-498198-40000
Error code: 1058-500952-40000
Error code: 1058-500954-40000
Error code format
| |
Error code description, taking 20502 as an example
| 2 | 05 | 02 |
|---|---|---|
| Service-level error (1 is a system-level error) | Service module code | Specific error code |
Some error codes:
| Error Code | Error Message | Detailed Description |
|---|---|---|
| 10014 | Service module Insufficient app permissions | The application’s API access permission is restricted |
| 20603 | List does not exists | The list does not exist |
| 20701 | Repeated tag text | Cannot submit the same collection tag |
The error codes of the Baidu Developer Center are encoded in an auto-incrementing way.
| Error Code | Error Message | Detailed Description |
|---|---|---|
| 0 | Success | Success |
| 1 | Unknown error | Unknown error |
| 2 | Service temporarily unavailable | Service temporarily unavailable |
| 100 | Invalid parameter | Invalid parameter |
| 101 | Invalid api key | Invalid API key |
| 102 | Invalid session key | Session key invalid or no longer valid |
| 103 | Invalid call_id parameter | Invalid/Used call id parameter |
The WeChat Open Platform uses five-digit error codes.
| Error Code | Error Message | Detailed Description |
|---|---|---|
| 40001 | invalid credential | Invalid call credential |
| 40008 | invalid message type | Invalid message_type |
| 40016 | invalid button size | Invalid number of menu buttons |
In the WeChat Pay related APIs, codes are encoded with uppercase English letters plus underscores.
| Error Code | Error Message | Detailed Description |
|---|---|---|
| NOAUTH | The merchant has no permission for this API | The merchant has not enabled the permission for this API |
| ORDERPAID | The merchant’s order has been paid, no need to repeat the operation | The merchant’s order has been paid, no further operation needed |
| SYSTEMERROR | System error | System timeout |
2.2 What Makes a Good Error Code
- Short enough
While meeting usage requirements and considering extensibility, a short error code is easier to maintain and update. The error codes of the Tencent Open Platform look particularly verbose; even if you have encountered an error once, it is still hard to recall on its second appearance.
- Contains more information
The error codes of the Sina Open Platform distinguish system-level and service-level errors by the first digit. This is followed closely by the module code and the specific error code, making it very easy to locate the error. Containing more information means a longer error code, which conflicts with the advice to keep it short enough. How to choose a suitable length needs to take the complexity of the system into account. If the system is very complex and needs to represent many states, then of course you should prioritize the system’s needs and use longer error codes that contain more error information.
Literal and self-explanatory
The error codes of the WeChat Pay platform are especially easy to understand. Through a few simple actions and keyword combinations, such as NO, LACK, DATA, PARAMS, you can guess the meaning of the error with near accuracy without a code lookup table. Of course, there are also some rather long error codes, likeOUT_TRADE_NO_USED, which are more laborious to encode and understand.Make full use of codes that have reached consensus
Returning 0 means the request is normal, returning <0 means an exception — no textual explanation is needed, and using consensus codes can significantly reduce communication costs. Note that there is another consensus, especially for web developers: the HTTP status code is the most important coding consensus. Both the Tencent Open Platform and the WeChat Open Platform use a large number of 4XXX codes for client errors and 5XXX for internal server errors. Without looking at an error code lookup table, developers can basically locate where the error occurred, and then use the lookup table to pin it down to the error in the program logic.
2.3 Error Code Design
2.3.1 Encoding by Module
| 1st digit | 2nd-3rd digit | 4th-5th digit |
|---|---|---|
| 2 | 05 | 02 |
| Service-level error (1 is a system-level error) | Service module code | Specific error code |
Divide the error codes into sections, use different sections to represent different modules, and then encode the errors. The number of error codes available with this encoding is subject to certain limits; for example, when 10100-10199 are used up, you are forced to occupy codes starting with 102 and 103. Of course, you can also reserve sufficient encoding space when designing error codes. For example:
| 1st digit | 2nd-4th digit | 5th-8th digit |
|---|---|---|
| 2 | 050 | 0200 |
2.3.2 Encoding with English Phrases
Common system error codes all use only Arabic numerals; for example, the error codes in the Windows system increase from 0000 to 15999. The advantage of using numbers is high processing efficiency and easy encoding. However, the meaning a single number can express is limited. If a phrase can be used to give the error prompt directly, it is more direct and effective.
| |
At the code level, the difference between encoding with English phrases and encoding with numbers is
| |
2.3.3 Encoding with a State Diagram
The essence of an application system is a finite state machine, and an error code represents one error state of the application system. Designing error codes means encoding the states of the application system.
Take a simple shopping web system as an example. The application system has only three logical modules: login, precondition check, and payment.

At this point, the application system has three nodes — login, front, pay — and six paths, ①②③④⑤.
| |
If a new processing node is added, exchange
| |
The advantage of encoding errors through a state diagram is that it can describe very precisely where the error occurred, and when the system is extended you only need to add nodes and edges. Here you can of course also use numbers for encoding, for example node login (100), front (101), path - ②⑤ (100101XXX).
3. How Django Handles Exceptions
When Debug = True, if an exception occurs, Django echoes the relevant information from program runtime onto the page, making it easier for developers to debug. As shown below:

When Debug = False, if an exception occurs, Django returns a custom or built-in 500, 404, etc. page. As shown below:

Now let’s look at how Django handles these exceptions:
3.1 How Django Handles a request
Taking local development as an example, when the browser initiates a request, the wsgi in Django creates a WSGIHandler object to handle the request. In the
WSGIHandler object the environment variables are initialized; if there is no exception, the self.get_response(request) function is called to handle the request and returns the response to wsgi.
get_response is defined in the django.core.handlers.base.py file; the processing flow is as follows.
| |
This diagram presents the whole processing flow logic fairly well.

3.2 ExceptionBox
Django’s middleware supports a kind of Exception form. When an uncaught exception occurs, the function process_exception defined in the middleware is executed; if it returns a response, then the whole flow can be ended.
In a Django project, a module for unified exception handling and error code management is needed. Hence ExceptionBox.
The data return format:
| |
__init__.py
| |
base.py
| |
error.py
| |
middleware.py
| |
my_view.py
| |
