Troubleshooting: archival channel enablement
Two archival gates can stall a send or an export mid-flow. Both are tenant-owned controls, and both refuse rather than half-commit — you read the posted control posture once, then fix it once.- Contact-archive freeze — a contact set to the
archivedlifecycle stage stops receiving dispatch and routes it out of the active funnel. - Archival-policy channel gate —
POST /compliance/archival/exportreturns409 ARCHIVAL_CHANNEL_NOT_ENABLEDwhen the export names a channel the policy does not enable (or when archival was never enabled). A legal-hold or archive flow that fans out over channels stops at the first blocked one.
Archival is a tenant-owned control: your org records the policy and
chooses the channels the immutable copies cover. The refuse below is the
platform honoring your recorded posture, not a platform fault — resolve
it from your side as below.
Contact-archive freeze
Archiving a contact is a freeze, not a delete. The row moves to thearchived lifecycle stage, drops out of the active funnel, and stops
receiving new dispatch — a campaign, a flow enrollment, or a one-off send
that targets it re-routes around it or refuses. This is what you want when
you set a contact aside under retention or legal-hold scope: the record
stays, but further sends cannot accidentally reach it.
It becomes a block when a later flow picks the archived row as a target —
a stalling send that never confirms. The freeze holds until the target is
explicitly unarchived: a plain PATCH /contacts/{id} that carries
lifecycle_stage for an archived row refuses with
409 CONTACT_ARCHIVED unless you pass the companion unarchive: true
flag in the same call. That guard stops an unrelated edit (a name change,
for example) from silently reactivating a contact you deliberately froze.
Fix — reactivate deliberately, or route around the frozen target:
- Confirm the target. Read the contact and check
lifecycle_stageisarchived. - Either nominate another, active contact for the send, or unarchive:
PATCH /contacts/{id}withlifecycle_stage: "active"(or whichever stage you want back) andunarchive: truein the same body. - Re-run the send or flow. The gate reads the stage synchronously, so the same dispatch goes through as soon as the row is active again.
Bulk pipelines (import wizards, bulk edits) are the common way a frozen
contact gets re-staged — the same
unarchive: true companion flag is
what those surfaces pass, and the same guard applies. If the send is a
legal-hold or archive flow, check the channel gate below before you
re-file.Archival channel not enabled
OnPOST /compliance/archival/export, 409 ARCHIVAL_CHANNEL_NOT_ENABLED
means the export named a channel — sms, mms, or voice (call
recordings) — that the archival policy does not include, or that archival
was never enabled on the org at all. The export refuses rather than
half-collecting a channel the policy excludes, because an immutable
bundle that silently skips an expected channel is worse than no bundle.
A legal-hold or archive workflow that fans out a bundle across channels
stalls at the first blocked channel: the request fails as a whole, so
the flow stops mid-request until the policy is read.
- Read the current policy with
GET /api/v1/compliance/archival. The response is always200and returns the recordedchannelslist — the exact posture the export gate crosses on every call. - If the channel is missing — or
enabledisfalseso the list never applies — upsert the policy withPUT /api/v1/compliance/archival, including the channel inchannels(owner/admin role required for the write). - Re-issue the same
POST /api/v1/compliance/archival/exportonce. The gate re-reads the policy on every call, so the same export passes the moment the channel is covered.
What not to do
- Do not re-file the request before reading the policy. The 409
response only tells you the named channel was not covered; it does not
tell you which channels ARE. Issue the same export again only after
GET /compliance/archivalreturns achannelslist that covers the channel — re-filing blind replays the same refuse. - Do not retry in a loop. The gate is deterministic — it re-reads the policy on every attempt and refuses until the channel is enabled. Loop retries burn your export rate-limit budget without moving the posture.
- Do not disable a contact’s freeze just to clear a send. The archived-stage freeze exists to guarantee the record stays put; if the freeze is in scope (retention, legal-hold), route the send around it rather than unarchiving it. Unarchive only when you deliberately want the row back in the active funnel.
- Do not ask for a second opinion from the error. The named
channelon the 409 and thelifecycle_stageon the contact row are the answer — read them, fix the posture once, and re-dispatch.
See also
- Archival & export — the full policy surface (destinations, WORM, legal hold, export formats).
- Recording integrity, legal hold, and QC failures — the recording-side legal-hold workflow.
- Troubleshooting hub — every runbook grouped by surface.