客戶用我們做的後台發一篇新文章:封面、內文圖都上傳好了,按下「發佈」,卻拿到一個乾巴巴的 404「Not Found」。最詭異的線索是——把一篇既有草稿改成「已發佈」不會出事,只有「新建即發佈」會。
POST /api/posts 404 in 1.7s ↳ (afterChange hook) payload.update(posts, id=剛建立的文章) → NotFound
我們的後台有個 afterChange hook:文章一發佈,就把它標記成「已寄送電子報」,並在背景通知訂閱者。這個 hook 裡呼叫了 payload.update() 去寫回那個標記——但沒有把 req 傳進去。
在 Payload + Postgres 底下,一次寫入是包在一筆交易裡的。新建文章時,那一列還在交易裡、尚未 commit;而 hook 的 update 沒帶 req,等於另外開了一條新連線/新交易去做事。新交易看不到還沒 commit 的那一列 → 用 id 查不到 → 丟 NotFound → 一路冒到最外層變成 404。
改既有草稿時,那一列早就 commit 存在,新交易查得到,所以沒事——這也正是它躲過我們第一輪測試的原因。
把 req 傳進去,讓 hook 的 update 加入同一筆交易:
await payload.update({ collection: "posts", id: doc.id, data: { newsletterSentAt: new Date().toISOString() }, req, // ← 關鍵:加入本次請求的交易 context: { skipNewsletter: true }, });
req(或 transactionID),否則你是在跟一筆還沒 commit 的資料賽跑。框架幫你把寫入包進交易是好事;但 hook 裡再開一個寫入時,記得讓它待在同一筆交易裡。一個沒傳的 req,就足以讓「看起來一定會過」的建立流程,在最後一步查不到自己剛寫的資料。





