Greenhouse 422 "candidate already exists in job" when the agent re-adds a past applicant
Fixes Greenhouse 422 "candidate already exists in job" on re-adds by checking existing applications first. Use when the agent re-submits past applicants. Key trigger: 422 on candidate creation for a known person.
Greenhouse 422 "candidate already exists in job" when the agent re-adds a past applicant
TL;DR
The candidate already has an application on that job, so creating another 422s. Before creating, search the job's candidates by email; if they exist, update or move the existing application instead of creating a new one. Re-adds are updates wearing a creation costume.
422 Unprocessable Entity: "candidate already exists in job"Steps
Search the job's existing candidates by email before creating. Expected: The existing application is found.
Update the existing application (or move its stage) instead of creating a new one. Expected: No 422, and history stays unified.
If the existing application is on a different job, use the appropriate endpoint for that case. Expected: The right object is touched.
Make the create path check-then-act, with the check and create as close together as possible. Expected: Races are minimized.
Log the already-exists path as a normal outcome, not an error; it is the common case for re-applicants. Expected: Metrics stop crying wolf.
When to use
- Greenhouse 422s with "candidate already exists in job"
- the agent re-adds past applicants
- re-applicants are common
When not to use
- the candidate is genuinely new (check the email normalization first)
- the error is on a different 422 (read the message; 422 has many meanings)
- duplicates are intended (rare; then handle the 422 explicitly)
Tool compatibility
- Greenhouse Harvest API
- candidate creation flows
Variant phrasings
- "greenhouse 422 candidate already exists"
- "candidate already exists in job fix"
- "greenhouse re-add applicant 422"
Why it happens
Greenhouse enforces one application per candidate per job. Re-applicants, referrals of past candidates, and bulk re-imports all hit this. The agent treated 'create' as the only verb; for existing candidates the verbs are 'update' and 'move'.
Edge cases
- email normalization (case, plus-addressing) decides whether the check finds the existing record
- the check-then-act still races under concurrency; handle the 422 as the backstop
- an existing application on a closed job needs reopening logic, not just a stage move
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_-BVdTnjNoKvUEDEGURVSwg