一個沒帶 req 的 update,讓「發新文章」噴 404
客戶專案踩坑
Ricky-
08 月 22,2026

客戶用我們做的後台發一篇新文章:封面、內文圖都上傳好了,按下「發佈」,卻拿到一個乾巴巴的 404「Not Found」。最詭異的線索是——把一篇既有草稿改成「已發佈」不會出事,只有「新建即發佈」會。

POST /api/posts 404 in 1.7s
  ↳ (afterChange hook) payload.update(posts, id=剛建立的文章) → NotFound
上傳 4 張圖 ✓ 各自的請求 建立文章 status=published afterChange hook.update ✗ NotFound → 404
前面每一步都成功,卡在最後 hook 回寫自己剛建立的那一列。

為什麼只有「新建」中招

我們的後台有個 afterChange hook:文章一發佈,就把它標記成「已寄送電子報」,並在背景通知訂閱者。這個 hook 裡呼叫了 payload.update() 去寫回那個標記——但沒有把 req 傳進去。

在 Payload + Postgres 底下,一次寫入是包在一筆交易裡的。新建文章時,那一列還在交易裡、尚未 commit;而 hook 的 update 沒帶 req,等於另外開了一條新連線/新交易去做事。新交易看不到還沒 commit 的那一列 → 用 id 查不到 → 丟 NotFound → 一路冒到最外層變成 404。

改既有草稿時,那一列早就 commit 存在,新交易查得到,所以沒事——這也正是它躲過我們第一輪測試的原因。

沒帶 req(壞) 交易 A · 建立文章 INSERT 新列 尚未 commit 交易 B · hook.update(新連線) SELECT … WHERE id = 新列 ✗ 查不到 → 404 看不到未 commit 的列 帶 req(好) 同一筆交易 A INSERT 新列(未 commit) update(req) 走同一交易 ✓ 看得到自己剛寫的列 COMMIT ✓ → 201 已發佈
差別只在 hook 的 update 有沒有加入「本次請求的交易」。

修法只有一行

把 req 傳進去,讓 hook 的 update 加入同一筆交易:

await payload.update({
  collection: "posts",
  id: doc.id,
  data: { newsletterSentAt: new Date().toISOString() },
  req,                       // ← 關鍵:加入本次請求的交易
  context: { skipNewsletter: true },
});

真正的教訓

  • 會寫入的 hook,要走請求本身的交易。傳 req(或 transactionID),否則你是在跟一筆還沒 commit 的資料賽跑。
  • 這個 bug 藏得住,是測試方式害的。我們驗收時走的是「改草稿 → 發佈」(列已存在),沒測「新建即發佈」——但使用者真正走的是後者。
  • 一句話:測試要測使用者真的會走的那條路,不是最好測的那條。(這條之後單獨寫一篇。)
帶得走的一句話

框架幫你把寫入包進交易是好事;但 hook 裡再開一個寫入時,記得讓它待在同一筆交易裡。一個沒傳的 req,就足以讓「看起來一定會過」的建立流程,在最後一步查不到自己剛寫的資料。

Tags:
Payload交易Hooks


相關文章
從零開始製作一個ip查詢網站-第一章 React 開發環境的準備
從零開始製作一個ip查詢網站-第一章 React 開發環境的準備
chris - 2025-11-24T11:28:35Z
從零開始打造 IP 查詢網站,本章節教你如何準備 React 開發環境,包括安裝 Node.js、使用 Vite 建立專案、安裝依賴套件並啟動開發伺服器。詳細說明每個步驟與常見坑點,幫助初學者快速上手...
從零開始製作一個ip查詢網站-第二章 獲取使用者的IP
從零開始製作一個ip查詢網站-第二章 獲取使用者的IP
chris - 2025-11-29T05:54:37Z
想知道自己的 IP 是多少,並為後續地理定位做準備嗎?這篇文章完整教你如何在 React 網頁中抓取使用者公開 IP,說明為什麼瀏覽器無法直接提供真實 IP,並示範使用免費的 ipify API 快速...
同一個測驗,我隔三年重寫了一次
同一個測驗,我隔三年重寫了一次
ricky - 2026-08-23T02:50:34.654532Z
2023 年寫的三個線上測驗,2026 年整個重寫。同一份題目、同一個作者,差別不在技術:當初沒問過「他們在什麼情況下用」,而課堂上一群人拿手機填,在程式碼裡留下了一頁到底、id 重複、把觸控目標縮小...
訂閱電子報
隨時掌握最新的創業故事與設計開發過程
內容包含來自麒航團隊的日常分享、專業知識與工具推薦,助你了解更多創業背後的思維與技術。
麒航私房推薦
Clelereve Blog LogoClelereve Blog LogoClelereve Blog Logo
廣告區
Clelereve Blog Logo
聯絡我們
任何合作或問題請洽:
clelereve@gmail.com
Follow us
Copyright © 2025 blog.clelereve.com - All Rights Reserved
Frontend Version: -- | Backend Version: --
創業實驗筆記 - Clelereve Blog | 一個沒帶 req 的 update,讓「發新文章」噴 404 | Clelereve Blog