Skip to content
Zarif Automates

Build an n8n Ticket-Triage Workflow and Test Its Failure Paths

ZarifZarif
|Published

A workflow that labels one clean ticket is easy to demonstrate. The harder question is what happens when the same event arrives twice, a ticket is missing, or the model returns something your application cannot accept.

This lesson gives you an importable n8n workflow with those cases already built in. Eight synthetic events pass through validation, lookup, a model-output fixture and a review gate. Two become review items. Six are rejected with reasons. Nothing sends a message or changes a ticket.

Download the inactive workflow JSON or get the workflow, input fixtures and recorded results together.

The workflow was executed locally with n8n 2.39.7 and Node 24.19.0 on September 17, 2026. It uses the real n8n execution engine and JavaScript Code nodes. Its model output is synthetic, so these results establish workflow behavior rather than model quality.

1. Import it without publishing

If you already use n8n's editor, create a new workflow, open its menu and choose Import from File. Select the downloaded JSON, inspect the ten nodes and keep the workflow unpublished. The file has active: false, one Manual Trigger, no credentials, no HTTP Request node and no schedule. The official import guide explains the file-import options.

The Manual Trigger lets you run the example deliberately. Select Execute Workflow, then inspect the three terminal nodes: Review items, Rejected events, and Rejected proposals. Their outputs should contain two, two and four items respectively.

For a repeatable local CLI run, use a new empty directory with Node 24 installed. Save the JSON there as ticket-triage.json. These macOS/Linux commands install the tested version and give it a separate local state directory:

node --version
npm init -y
npm install n8n@2.39.7
export N8N_USER_FOLDER="$PWD/n8n-test-state"
export N8N_DIAGNOSTICS_ENABLED=false
export N8N_VERSION_NOTIFICATIONS_ENABLED=false
export N8N_TEMPLATES_ENABLED=false
export N8N_PERSONALIZATION_ENABLED=false
export N8N_RUNNERS_BROKER_LISTEN_ADDRESS=127.0.0.1
export N8N_RUNNERS_BROKER_PORT=15689
npx n8n import:workflow --input=ticket-triage.json
npx n8n execute --id=ZarifTicketLab01 --rawOutput

Use that isolated state directory for the exercise: importing a workflow with an ID already present in another database can replace it. If port 15689 is occupied, choose another local port. No public server or tunnel is needed.

The Server CLI documentation describes importing a saved workflow and executing it by ID. The tested release rejects the older execute --file shortcut, so import first. Startup messages may precede the JSON execution data. This JavaScript-only run also logged that the optional Python runner was unavailable; the JS Task Runner registered and executed the Code nodes successfully.

2. Follow the data through the nodes

Manual test → Synthetic events → Validate events → Event valid?
                                                   ├─ false → Rejected events
                                                   └─ true  → Lookup and model fixture
                                                              → Validate proposals
                                                              → Proposal valid?
                                                                 ├─ true  → Review items
                                                                 └─ false → Rejected proposals

Every Code node uses Run Once for All Items. In the Code node's all-items mode, $input.all() supplies the input items. The transformations return objects with json data and retain each item's link to its input through pairedItem.

NodeConfiguration to inspect
Synthetic eventsEight explicit input objects, including failures
Validate eventsRequired field types; integer version; duplicate IDs within this batch
Event valid?Strict Boolean condition on event_valid; false output goes to Rejected events
Lookup and model fixtureTwo synthetic tickets at version 3; controlled good, invalid and malformed model output
Validate proposalsTicket exists; version matches; JSON has exactly one allowed label
Proposal valid?Strict Boolean condition on proposal_valid
Review itemsEmits a proposal with state: awaiting_review and applied: false
Rejected events / proposalsRetain event ID and reason; never mark the change applied

The lookup and model step is deliberately a fixture. You can inspect every input that reaches it and make it fail without paying for a model call or touching another system.

3. Read the eight results

The fixture named evt-1 appears twice. The first copy is accepted for review; the second is rejected within that execution. The terminal outputs from the recorded run were:

EventCaseResult
evt-1, first copyValid billing proposalAwaiting review
evt-1, second copyRepeated event IDduplicate_event_in_batch
evt-2Missing ticketticket_not_found
evt-3Label delete-accountinvalid_label_contract
evt-4Version supplied as a stringinvalid_event
evt-5Valid technical proposalAwaiting review
evt-6Text that is not JSONinvalid_json
evt-7Version 2 against current version 3stale_version

An accepted review item looks like this:

{
  "event_id": "evt-1",
  "ticket_id": "DEMO-42",
  "expected_version": 3,
  "proposed_label": "billing",
  "state": "awaiting_review",
  "applied": false
}

There are eight input events, two review items, six rejections, and zero applied changes. These are counts for this fixture run, not an accuracy score. A workflow can route every item as designed while the underlying model is still wrong about its labels.

4. Change one failure and rerun

Open Synthetic events and change evt-3 from the invalid-label fixture to the default case by removing its fixture field. Execute the workflow again. You should now see three review items and five rejections.

Next restore the original fixture and change evt-7 to expected_version: 3. Its stale-version rejection should become a review item. Keep a copy of the original export so you can restore the eight-case baseline.

Then inspect Validate proposals. Its JSON parser and allowed-label check decide whether an output can proceed. Connecting the model node directly to a write node would skip that check. Keep the validation step visible even after the happy path works.

5. Know what must change for a real integration

The example's duplicate detector is a JavaScript Set created for one batch. Running the workflow again starts a new set and produces the review items again. This is not durable deduplication across executions or restarts. Before processing real deliveries, use a persistent store with a unique event ID and an atomic claim of work; test concurrent deliveries against it.

The review items also exist in execution output, not in a staffed approval queue. To extend the workflow, choose a durable review destination and record the exact proposal, record version, decision, reviewer and expiry. A separate executor should recheck the version when applying an approved change.

Replace the synthetic lookup and model fixture with real nodes only after choosing their credentials and record scope. Preserve the same proposed-label contract and run the failure cases again. Test model behavior separately with representative, permitted data; passing these fixture branches does not establish live model accuracy.

Finally, add the actual provider's webhook verification and a bounded error policy. n8n's error-handling guide covers error workflows, but expected input rejections and unexpected execution failures deserve different handling. Do not retry a completed external write merely because its response was lost.

Your deliverable is the imported workflow, the eight-case baseline and one changed fixture with the expected new counts. Keep it unpublished until you have designed and tested the external boundaries. Continue to the agent capstone to connect the course's components into one inspectable application.

Zarif

Zarif

Zarif builds AI agents and automation workflows and writes about what holds up in production: the sources worth following, the roles the AI era is creating, and agent workflows you can inspect end to end.