Troubleshooting: campaign and journey enrollment errors
Enrollment and graph-validation errors are refused at the door — before any contact enters the journey, and before a single message is sent. This page covers the four campaign-side refusal codes, the four journey-graph validation codes, and the one executor-recovery code on the resume path. For failures that happen inside a running journey (failed execution rows, misbehaving nodes), see
Troubleshooting: a flow execution that failed.
The four surfaces this page debugs:
The first two are the enrollment endpoints; the third refuses
AUDIENCE_TOO_LARGE at launch; the fourth hits the re-validation
safeguard covered below.
The enrollment validation flow
Every enrollment request runs the same gate sequence. The first gate that fails returns its own code, so the response tells you which step rejected it:Campaign-side refusals
These codes come from the campaign record or the launch itself — the graph never gets looked at.Journey-graph validation
These codes mean the campaign’s step graph could not resolve an entry point. Fix the graph in the campaign editor, then retry enrollment.JOURNEY_DEFINITION_INVALID, JOURNEY_TRIGGER_MISSING, and
JOURNEY_TRIGGER_DISCONNECTED fire at enrollment time;
JOURNEY_VALIDATION_FAILED fires at resume time. Same validator,
different gate.
Executor recovery: RESUME_FAILED and the resume safeguard
When a journey enrollment pauses (a delay node, a send-time schedule),
the scheduler later calls the resume endpoint to continue that contact.
Two outcomes matter on that path:
JOURNEY_VALIDATION_FAILED(400) — the resume safeguard. Before the executor runs a single node, the stored journey definition is re-validated. If someone edited the graph after the campaign started (deleted the trigger, orphaned a node the paused enrollment was parked on), resume refuses and the response names the validation error. This refusal is a safeguard catching a graph drift, not a user error you need to retry through — fix the graph, and the scheduler picks the enrollment up on its next sweep.RESUME_FAILED(500) — the executor itself threw mid-resume (the message field carries the underlying error). The scheduler counts the attempt, backs off exponentially, and retries; after its attempt ceiling it stops retrying the enrollment instead of looping on it. ARESUME_FAILEDthat keeps recurring on the same enrollment after the upstream cause is fixed (a dead webhook, an upstream 5xx) should be escalated with the campaign id, contact id, and tenant id.
400 refusal stops retrying precisely because retrying cannot change
it.
When to escalate
Escalate to support with the campaign id, the raw error response, and your tenant id (Settings → Organization) when:- The same contact gets
ALREADY_ENROLLEDafter its earlier enrollment visibly completed or was cancelled. - A graph reads valid in the editor but enrollment still returns
JOURNEY_DEFINITION_INVALID(a stale definition is usually the culprit; export the campaign as JSON so support can diff). RESUME_FAILEDpersists across backoff cycles after the upstream cause is fixed, or resume attempts drain without a resolution.
See also
- Campaign lifecycle — which statuses
gate enrollment (
running) and whereblastdiffers fromjourney. - Flow execution model — how journeys execute once enrolled, pause, and resume.
- Troubleshooting: a flow execution that failed — executor-level failures after a contact is enrolled.
- Error codes — the full catalog this page narrows to enrollment and graph errors.