owned this note
owned this note
Published
Linked with GitHub
# Data Process Error Handling Tips
## When ```handleError()``` Would be Called
In every LOC data process' generic/aggregator logics, there is a ```handleError``` function:
```javascript
async function handleError(ctx, error) {
ctx.agents.logging.error(error.message); // log the error
}
```
:::info
Use ```export async function handleError``` if you are using ++[LOC CLI](https://hackmd.io/4LIsNIuWQnuR70JMeuBAEA)++.
:::
If any error was thrown in a logic, its ```handleError()``` would be called. More importantly, *all* ```handleError()``` of the subsequent logics - including the aggregator - will also be called with the same error passed into these functions. (In other words, the data process task was *failed*.)
For example, in the following table, an error occurred in generic logic #3. All ```handleError()``` from generic logic #3 until the aggregator logic will be called (with the error from #3 pass down all the way):
| Logics | Error occurred? | Called function |
| ---------- | --------------- | ------------------- |
| generic #1 | No | ```run()``` |
| generic #2 | No | ```run()``` |
| generic #3 | Yes | ```handleError()``` |
| generic #4 | N/A | ```handleError()``` |
| generic #5 | N/A | ```handleError()``` |
| aggregator | N/A | ```handleError()``` |
## Return Error Result in Aggregator
Under normal circumstances, the aggregator wouldn't be able to produce any meaningful result whenever one of its logics fail. However, we can still return the error with ```ctx.agents.result```:
```javascript
// error handling in aggregator
async function handleError(ctx, error) {
ctx.agents.result.finalize({
error: error.message, // return the error as part of the result
taskId: ctx.task.taskId,
});
}
```
This allows users to see some useful information in the API route response or logging, etc. Even though the error message is null due to some reason, the ```error``` field still indicates that some error had occurred.
## Use ```try/catch``` to Intercept Errors
Sometimes you do hope other logics can keep running even though some logics may encounter (expected) errors. You can use [**try/catch**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling) to handle errors yourself and avoid task failure:
```javascript
// logic in aggregator
async function run(ctx) {
try {
// something that might went wrong
} catch (error) {
// if something went wrong, get an error
// log the error
ctx.agents.logging.error(error.message);
// store the error in session store
await ctx.agents.sessionStorage.putString("logic_01_error", error.message);
} finally {
// do things that need to be done
// whether there are errors or not
}
}
```
And you can store error in the same way in the 2^nd^ logic (as ```logic_02_error```), 3^rd^ logic (as ```logic_03_error```), and so on.
:::info
You can use multiple ```try/catch``` blocks in any logics to intercept different errors.
:::
Finally, in the aggregator, you can check each of the errors from all logics:
```javascript
async function run(ctx) {
// read potential errors from all logics
const logic_01_error = await ctx.agents.sessionStorage.get("logic_01_error");
const logic_02_error = await ctx.agents.sessionStorage.get("logic_02_error");
...
let status = 200;
// check if there are errors; if so, set our custom status as 500
if (logic_01_error & logic_02_error ...) {
status = 500;
}
ctx.agents.result.finalize({
status: status,
taskId: ctx.task.taskId,
error: { // if a field value is null, it means no error in that logic
logic_01_error: logic_01_error,
logic_02_error: logic_02_error,
...
}
});
}
```
## Throwing Error
However, there may be times that some errors caught by ```try/catch``` are simply too serious to allow the data process to continue. For situations like this, you can deliberately **throw** an error to trigger the ```handleError()``` mechanism:
```javascript
async function run(ctx) {
try {
...
} catch (error) {
if (error instanceof TypeError) { // if error is a TypeError
hrow new TypeError("There is a TypeError...")
} else if (error.message != "xxx") {
throw new Error("There is some error...")
}
} finally {
// do things that need to be done
// whether there are errors or not
}
}
```
Since we've thrown unhandled errors, the data process' ```handleError()``` will take over and do the rest.
:::info
**Error** is the most generic error type; see ++[Error types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#error_types)++ for possible JavaScript error types. You can also define ++[custom error types](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types)++.
:::
###### tags: `LOC Studio` `LOC CLI`