Skip to content
当前有符合你浏览器所设置语言的版本,是否前往zh-CN版本的网站?
There is a version suitable for your browser's language settings. Would you like to go to the zh-CN language of the site?
HomeDocument

Error Handling

H1

When developing applications, we often encounter two types of failure scenarios. One type of failure is directly related to the business process, such as when a user does not exist or when the order status has changed. The other type of failure is caused by unexpected errors, such as network issues or system resource overflows.

For failures related to the business process, we can use the reject method to actively throw errors and provide clear feedback to the client about the failure. For example:

if (!user) throw reject("NOT_FOUND", undefined);

In this way, we can precisely communicate the reason for the request failure to the client, enhancing the robustness and reliability of the system. The caller will receive a response in the following format:

{
"success": false,
"fail": {
"code": "NOT_FOUND",
"message": "Not Found",
"data": undefined
}
}

Callers can easily determine the success of the request using code.success and identify the specific type of failure using fail.code. This design helps in clearly conveying the request status, making it easier for the caller to handle and respond to failure scenarios effectively.

Error Codes

In the /src/fail-code.ts file, we have defined all possible error codes.

Each key corresponds to a specific error code, and its value is a function that returns a string describing the reason for the failure. This design facilitates the management and clear organization of different error codes, providing detailed explanations for each error code.

/src/fail-code.ts
import type { MilkioFailCode } from "milkio";
export const failCode: MilkioFailCode = {
NETWORK_ERROR: () => "Network Error",
INTERNAL_SERVER_ERROR: () => "Internal Server Error",
NOT_FOUND: () => "Not Found",
NOT_ALLOW_METHOD: () => "Method Not Allowed",
TYPE_SAFE_ERROR: (data) => `Parameter Error: Current value '${data.value}' does not meet the requirements of '${data.expected}'`,
BUSINESS_FAIL: (data) => `${data}`,
// More custom error codes can be added here
// ...
};

Parameter Passing

When calling the reject method, you can adjust the error message sent to the client through parameters. This allows developers to flexibly customize error messages as needed.

throw reject("ACCESS_EXCEEDED", { path: "/foo/bar", counter: 64 });

Please note that the method only accepts one parameter. If you need to pass multiple parameters, you can achieve this by returning an object, as shown below:

/src/fail-code.ts
export const failCode = {
ACCESS_EXCEEDED: (data: {path: string, counter: number}) => `Access exceeded. Path '${data.path}' only allows access ${data.counter} times.`,
} satisfies MilkioFailCode;

These parameters will also be sent to the client for further processing. The client will receive a response in the following format:

{
"success": false,
"fail": {
"code": "ACCESS_EXCEEDED",
"message": "Access exceeded. Path '/foo/bar' only allows access 64 times.",
"data": { path: "/foo/bar", counter: 64 }
}
}

Business Failures

Most failures stem from business logic, such as exceeding a deadline or insufficient inventory. For these localized business failures, we usually only need to inform the user of the reason for the failure. In such cases, we can uniformly use the BUSINESS_FAIL status code:

throw reject("BUSINESS_FAIL", "Activity has not started yet, sales start at 3 a.m.");

Unexpected Errors

For any uncaptured errors, the client will receive a fixed INTERNAL_SERVER_ERROR error code to prevent sensitive information leakage.

User-Friendly Error Messages

Error messages should explain the reason for failure to users, but not all messages are user-friendly enough. For example, in the case of a TYPE_SAFE_ERROR failure caused by insufficient password length, we may not want to directly show the user:

Parameter Error: Current value is '$input.user.password', does not meet the requirements of 'string & tags.MinLength<8>'.

Instead, we would prefer the user to see a more friendly prompt:

Password is too short, please try entering at least 8 characters.

It is recommended that this user-friendly error message handling be done on the client side. The benefits include:

  • Achieving thorough decoupling between the front end and back end.
  • Simplifying the implementation of language switching functionality, without the need to handle it on both the client and server sides.
  • Ensuring that the client is always responsible for writing user-friendly error messages.

For more information, please refer to Milkio Client.