agent sent duplicate interview confirmations - the idempotency key was the candidate email but the retry used a...
Fixes duplicate interview confirmations caused by an idempotency key built from an email whose casing changed between attempts. Use when retries or re-runs of a confirmation send produce a second email. Key trigger: same candidate, two confirmations, different email casing in the logs.
Duplicate interview confirmations from an idempotency key with drifting email casing
TL;DR
The first confirmation built its idempotency key from one casing of the candidate email and the retry used another, so the dedupe lookup missed and the email went out twice. Fix: normalize the key material (lowercase, trim) the same way on every attempt, or better, key on the interview or event ID instead of the email. Idempotency only works when the key is byte-identical across attempts.
Error
agent sent duplicate interview confirmations - the idempotency key was the candidate email but the retry used a different-case normalized emailSteps
Confirm the pattern: find duplicate confirmation pairs in the logs and compare the key material used for each attempt. Expected: same candidate, different key strings, e.g. casing differences.
Centralize key building in one function: lowercase, trim whitespace, then hash. Every retry path must call this same function. Expected: identical input always yields identical keys.
Prefer a stable key: use the interview or event ID plus the action name instead of the email. IDs do not have casing problems. Expected: a key like interview [ID] plus "confirmation" that never varies.
Store sent confirmations keyed by the idempotency key and check the store before sending. Expected: the retry finds the first send and skips.
Replay a test: send a confirmation, then retry with mixed-case email. Expected: one email total; the retry logs "already sent".
Use this when
- retries produce duplicate sends
- idempotency keys are built from emails, names, or other free text
- logs show the same action twice with slightly different keys
- multiple code paths build the key
Not for this skill when
- both confirmations came from two different agents (that is the scheduler-vs-outreach problem)
- the duplicate is the same email resent by a restarted batch (that is sent-state loss)
- the key was identical but the store check was skipped (that is a missing dedupe check, not key drift)
Variant phrasings
- "idempotency key case mismatch"
- "duplicate confirmation email retry"
- "email normalization broke dedupe"
- "same candidate two confirmations"
Why it happens
Email addresses are case-insensitive by convention but case-sensitive as strings. Two code paths normalized differently (or one did not normalize at all), so the "same" key differed by bytes and the dedupe store treated them as different actions. Idempotency is a string-equality contract; any drift in how the string is built breaks it silently.
Edge cases
- Plus-addressed variants (name plus tag forms) can create distinct keys for one inbox; decide whether to fold them.
- Internationalized emails need Unicode normalization, not just lowercasing.
- If keys expire from the store, a late retry duplicates; set key TTL longer than your retry window.
- Do not include timestamps in the key or every attempt is unique by construction.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstoellMNCbaGpAtgZWdFWow