Troubleshooting: pending-compliance and erasure gates
A GDPR Article-17 erasure request owns the contact for the life of the request: from the moment you file it until the scheduled hard-delete runs (or you cancel), a small class of pre-write checks refuse operations against that contact. The refusal is deliberate — your own erasure request is holding the contact, not a platform verdict you need to appeal. Two error codes share that shape:CONTACT_ERASURE_PENDING— an outbound send to the contact is refused while an erasure request for them is pending or executing.ERASURE_COOLING_OFF_ACTIVE— a new erasure filing is refused because a pending or executing request already exists for the contact.
Cause table
The cooling-off window is per-tenant configurable and defaults to
7 days. While a request is pending inside it:
- erasure-request filings, message sends, and other contact writes to that contact are refused,
- the request stays cancellable — once the window lapses, the scheduler hard-deletes the contact and writes a per-resource audit chain, and the request is no longer cancellable.
GET /contacts/:id/gdpr/erasure-requests — each row carries
status (pending, executing, cancelled, completed) and
cooling_off_ends_at.
CONTACT_ERASURE_PENDING (422)
The send pipeline checks the recipient before dispatch. A contact with a
pending or executing erasure request fails that check, and the send never
reaches the provider — for a campaign the recipient row is marked
skipped with reason: "erasure_pending"; for a direct API send the
error arrives in the standard envelope:
- Cancel the erasure if the send is required — while the request is
still
pending, callPOST /contacts/:id/gdpr/erasure-request/:requestId/cancel(an optionalreasonis recorded on the audit trail). Sends to the contact unblock immediately. - Or wait for the window. When
cooling_off_ends_atlapses, the scheduler hard-deletes the contact and writes the per-resource audit chain. After that, a send to the same address behaves as a send to an unregistered recipient. - Do not retry-loop the 422. The refusal is deterministic for the life of the request — it clears only on a cancellation or on the hard-delete.
ERASURE_COOLING_OFF_ACTIVE (409)
POST /contacts/:id/gdpr/erasure-request enforces one active erasure
request per contact. A second filing lands on that uniqueness rule before
anything is written, and the endpoint returns the 409 — the existing
request is either still cancellable (pending) or already executing.
Fix.
- List the contact’s requests to find the active one:
GET /contacts/:id/gdpr/erasure-requests— the active row is the one withstatuspendingorexecuting. - If the active request is
pending, cancel it withPOST /contacts/:id/gdpr/erasure-request/:requestId/cancel, then re-file your new request — a corrected filing always goes through the cancel. - If the active request is
executing(or has completed), cancel is no longer available; the scheduled hard-delete is imminent or done — treat the conflict as already resolved and file the new request only if data for the contact still exists.
DSAR_NOT_CANCELLABLE is a different, terminal gate
DSAR_NOT_CANCELLABLE (409) is the terminal state of the cancel path —
it means the request cannot be withdrawn because it does not exist or has
already completed, failed, expired, or been cancelled. It is not an
erasure-ownership gate like the two codes above; read the request status
first with GET /compliance/dsar/:id and treat the 409 as the answer, not
a retryable error. Its full recovery matrix sits on
Troubleshooting: DSAR export, decrypt, and cancel failures.
Recovery summary
Every control on this page is a tenant-owned path: Orbit runs the
erasure lifecycle and the pre-write gates; whether you cancel a request
or wait for the cooling-off window — and how you fulfil the data
subject’s request — is your call. Nothing here is a claim of GDPR, CCPA,
or other compliance.
Related references
- Data Subject Access Requests — the DSAR lifecycle the gates above belong to.
- Troubleshooting: DSAR export, decrypt, and cancel failures —
the export/decrypt pipeline and the terminal
DSAR_NOT_CANCELLABLEgate. - Error codes — the registry entries for
CONTACT_ERASURE_PENDING,ERASURE_COOLING_OFF_ACTIVE, andDSAR_NOT_CANCELLABLE.