Rules
Each rule names one way a handler goes wrong when it runs twice or stops halfway. Configure them in retrysafe.config.ts (rules: { "rule-id": "off" }) or silence one line with // retrysafe-ignore <rule> -- <reason>.
- error
check-then-insert-raceA lookup-then-insert dedupe check with no atomic claim before the effect; concurrent duplicates both pass it.
- error
incrementing-write-unguardedA relative write (increment, x = x + n, $inc, push) runs with no dedupe guard.
- error
nondeterministic-keyA dedupe or idempotency key is derived from Date.now(), Math.random(), uuid(), or similar.
- error
record-before-effect-no-txThe event is marked processed before its work runs, outside one transaction and with no rollback.
- error
swallowed-error-returns-2xxA catch block swallows a failure of the handler's work and still acknowledges the event (2xx, or a completed job).
- error
unguarded-side-effectA non-idempotent effect (payment, email, plain insert, increment) runs with no dedupe guard on its path.
- warning
ack-timingThe response is sent before the work completes (or the work is not awaited), or slow work delays the response past the provider's timeout.
- warning
dedupe-ttl-shortA dedupe key expires sooner than the provider's retry window.
- warning
effect-before-recordAn effect runs before the event is recorded, behind a check that is not an atomic claim.
- warning
effect-missing-idempotency-keyA call whose SDK supports an idempotency key is made without one.
- warning
non-atomic-multi-writeSeveral database writes on one path run outside a transaction, and at least one is not idempotent.
- warning
permanent-error-returns-5xxA permanent failure (invalid signature, malformed payload) is answered with 5xx, causing pointless retries.
- warning
retry-loop-with-effectAn in-code retry (loop, p-retry, async-retry) wraps a non-idempotent call that has no stable idempotency key.
- warning
wrong-event-field-as-keyA dedupe key is derived from the object id inside the event (e.g. event.data.object.id) rather than the event id.
- info
order-dependence-assumedThe handler sets state from several event types without checking a version or timestamp.
- info
queue-add-without-job-idA job or message is enqueued without the queue's deduplication id (jobId, MessageDeduplicationId, event id).