The problem
In RAG's generation hook the writer lookup sits outside the try that exists to keep failures from escaping. So a throw from that lookup surfaces as an AfterTransactionError from a write whose row has already committed.
That is exactly the contract the hook's own Known limits block promises not to break: it says failures are logged, not thrown, precisely because the hook runs after commit and a caller who reads a throw as "the write failed" will retry and create a duplicate row.
Reachability is low — a plugin runtime that throws is caught and logged one level up — but the contract is wrong wherever it is reached, and it is wrong in the direction that costs a duplicate row.
Why this one matters more than its size
This is the first defect this delivery ever found, recurring. The original finding on the RAG work was that a provider failure threw out of an already-committed write, so a caller retrying created a duplicate. That was fixed by wrapping generate-and-write in a try and classifying the failure. Then a later round split the classification by inspecting the error rather than the code path.
The lookup was simply never moved inside the guard. Same shape, same consequence, in the same function, after two rounds of work specifically on that function's failure handling.
What to do
Move the lookup inside the try, and classify its failure the way the others are classified — a missing writer is a permanent misconfiguration, not something to retry.
Then check the whole hook for any other statement outside the guard, since the guard's purpose is that nothing in a post-commit hook throws.
Context
_Generated by Claude Code
The problem
In RAG's generation hook the writer lookup sits outside the
trythat exists to keep failures from escaping. So a throw from that lookup surfaces as anAfterTransactionErrorfrom a write whose row has already committed.That is exactly the contract the hook's own
Known limitsblock promises not to break: it says failures are logged, not thrown, precisely because the hook runs after commit and a caller who reads a throw as "the write failed" will retry and create a duplicate row.Reachability is low — a plugin runtime that throws is caught and logged one level up — but the contract is wrong wherever it is reached, and it is wrong in the direction that costs a duplicate row.
Why this one matters more than its size
This is the first defect this delivery ever found, recurring. The original finding on the RAG work was that a provider failure threw out of an already-committed write, so a caller retrying created a duplicate. That was fixed by wrapping generate-and-write in a
tryand classifying the failure. Then a later round split the classification by inspecting the error rather than the code path.The lookup was simply never moved inside the guard. Same shape, same consequence, in the same function, after two rounds of work specifically on that function's failure handling.
What to do
Move the lookup inside the
try, and classify its failure the way the others are classified — a missing writer is a permanent misconfiguration, not something to retry.Then check the whole hook for any other statement outside the guard, since the guard's purpose is that nothing in a post-commit hook throws.
Context
_Generated by Claude Code