---
# System prepended metadata

title: "\U0001F3C5 Day 28 - 錯誤處理 middleware、自訂錯誤訊息"
tags: [2025 Node.js 後端工程師培訓營]

---

# 🏅 Day 28 - 錯誤處理 middleware、自訂錯誤訊息

### 錯誤處理（error handler）middleware
在 `app.js` 可以撰寫錯誤處理的程式碼，當錯誤發生時，就會進入下方錯誤處理 middleware 回傳我們自訂的錯誤訊息

`app.js`
```javascript=
// 錯誤處理的 middleware 相較一般 middleware 會多一個 err 引數
app.use((err, req, res, next) => {
  err.statusCode = err.statusCode || 500;
  err.status = err.status || 'error';
  res.status(err.statusCode).json({
    status: err.status,
    message: err.message
  });
});
```

### 自訂錯誤訊息
我們可以另外新增自定義錯誤訊息的模組，在預期使用者可能會出錯的地方驗證錯誤（像是：xx 資料未填寫時，即可跳出自訂錯誤訊息）

撰寫流程：
自訂一個 appError function，將狀態碼及自訂錯誤訊息及 next 參數傳到 function 中。
使用 `new Error()` 帶入自訂錯誤訊息，建立 Error 物件，並設定 Error 回傳的資訊：`statusCode` 狀態碼、`isOperational` ，其中 `isOperational` 代表是否為**可預期**的錯誤，因是自訂的錯誤，通常都會設定為 true（可預期）
最後使用 `next()` 將 Error 交給 `app.js` 中的錯誤處理 middleware 回傳錯誤訊息

**範例**（較完整範例可觀看此 [GitHub](https://github.com/gonsakon/express-week4-sample/blob/week5/service/appError.js)）

`appError.js`
```javascript
const appError = (httpStatus, errMessage, next) => {
  const error = new Error(errMessage);
  error.statusCode = httpStatus;
  error.isOperational = true;
  next(error);
};
module.exports = appError;
```


### 參考資源
- [Error - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
- [Express 錯誤處理](https://expressjs.com/zh-tw/guide/error-handling.html)


題目
---
請嘗試將以下 POST 路由中的程式碼使用 `appError()` 加入以下自訂錯誤資訊
> statusCode: 400
> message: '欄位未填寫正確：貼文內容為必填'

當新增貼文時，若使用者未輸入內容 `content` 就需要跳出自訂的錯誤訊息。

`routes/posts.js`
```javascript=
router.post('/', async (req, res, next) =>  {
  try {
    const data = req.body;
    if (!data.content) {
      // appError 自訂錯誤回饋
      return next(...);
    }
    const newPost = await Post.create(
      {
        user: data.user,
        content: data.content,
        tags: data.tags,
        type: data.type
      }
    );
    res.status(200).json({
      status: 'success',
      data: newPost
    });
  } catch (error) {
    next(error);
  }
});
```

## 回報流程

將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 
解答位置請參考下圖（需打開程式碼的部分觀看）

![](https://i.imgur.com/vftL5i0.png)

<!-- 解答：  

```javascript=
router.post('/', async (req, res, next) =>  {
  try {
    const data = req.body;
    if (!data.content) {
      // appError 自訂錯誤回饋
      return next(appError(400, '欄位未填寫正確：貼文內容為必填', next));
    }
    const newPost = await Post.create(
      {
        user: data.user,
        content: data.content,
        tags: data.tags,
        type: data.type
      }
    );
    res.status(200).json({
      status: 'success',
      data: newPost
    });
  } catch (error) {
    next(error);
  }
});
```
-->




回報區
---
<!-- 
將答案貼至下方表格內，格式：
| Discord 暱稱 | [CodePen](連結) |
-->

|  Discord  |                           CodePen ／ 答案                           |
|:---------:|:-------------------------------------------------------------------:|
| bian_yang_mofa | [CodePen](https://codepen.io/cssf998811/pen/PwoZbPg?editors=0010)|
| sui_hsilan | [CodePen](https://codepen.io/suihsilan/pen/ByajQWB?editors=0010)|
| poyi | [CodePen](https://codepen.io/poyi-the-flexboxer/pen/qEBbmdp?editors=1010) |
|janetlai|[CodePen](https://codepen.io/eiddkqxz-the-builder/pen/XJWXarv?editors=1111)|
|adengg|[CodePen](https://codepen.io/Osases/pen/dPyGJRW?editors=0010)
|Tau|[CodePen](https://codepen.io/Tau-Hsu/pen/dPyGdNj?editors=0010)
|ZoeKang|[CodePen](https://codepen.io/byehywmx-the-animator/pen/qEBbKEV?editors=0010)
|JC|[CodePen](https://codepen.io/lifetimingwhisper/pen/ByaKKzE)
|helena|[CodePen](https://codepen.io/helena27/pen/WbNwEgL)
|sian|[CodePen](https://codepen.io/uxitysjl-the-flexboxer/pen/jEOrNgr)
|HarryKuo|[CodePen](https://codepen.io/harry_kuo/pen/XJWNarZ?editors=0010)|
|li wei-min|[CodePen](https://codepen.io/leewayne/pen/NPWgvjm)|
| hsin yu |[CodePen](https://codepen.io/tina2793778/pen/raNzBGY)|
|wuyuli_21403|[Codepen](https://codepen.io/Job-Wilhelm/pen/OPJjJNW?editors=0010)|
