Debugging and logs

Find out why a workflow did or didn't run. Covers live logs in the builder, failed-run records from the processes API, reading their context, the most common error messages, and a checklist for workflows that silently do nothing.

A workflow that misbehaves either fails (a step throws, and Kustomer records the error) or does nothing (no error, but no effect either). Failures are easy to find. Doing nothing usually means a condition didn't match, and the logs show you which one. For how a run moves from step to step, see How workflows run.

ToolShowsRetention
View Logs in the builderEvery run, step by step, with each step's input and outputRecords for one hour after you turn on Debug Mode. Shows the 100 most recent runs
View errors in the builder, or View Error Logs on the Workflows listFailed runs: "Failed with Error at step …". System retries aren't listedRecent failures. Clear All Errors empties the list
GET /v1/workflows/{id}/processesFailed runs, with the triggering event and the full contextPaginated history
lastError on GET /v1/workflows/{id}The most recent failureLatest only
Inbound hook debug logsWhat a hook received24 hours

Watch runs live

  1. Open the logger

    Open the workflow and select View Logs to open Workflow Log Events. Turn on Debug Mode. Kustomer records the workflow's runs for the next hour, which sets logging: true on the workflow.

  2. Cause the trigger

    Do the thing that should start the workflow, such as updating a test conversation. Remember that a workflow you just saved can take about a minute to start matching.

  3. Refresh and inspect

    Refresh the logger. Each run is listed as a log event with when it completed, how long it took and its last step. Open a run to see every logged step, then select a step to see its input and output. If nothing ran, the logger shows "No applicable logs".

Each step's output is exactly what /#steps.<id> refers to.

A step's output in the logger is what /#steps.<id> resolves to in later steps. If a param is coming out empty, compare its path with the output of the step it references. A misspelled field or the wrong step ID is the most common cause. Remember that the numbers on the canvas are positions, not step IDs.

Each logged run records, for every step, its input, its output, whether it succeeded and when it ran, plus the workflow version that ran. Secrets that Kustomer adds to a step's input are removed from the log. A param that's missing from a step's input usually means its reference resolved to null or undefined, so the param wasn't sent.

Read failed runs with the API

Every failed run is stored as a process. List a workflow's failures, newest first, optionally filtered by date:

Shell
kusty api GET /v1/workflows/$WORKFLOW_ID/processes --query createdAtFrom=2026-10-20T00:00:00Z --query pageSize=20 --output json
One failed run (abridged)
{
  "type": "workflowProcess",
  "id": "5eea124bccb9de001933f317",
  "attributes": {
    "status": "failed",
    "createdAt": "2026-10-21T12:53:30.684Z",
    "error": "{\"message\":\"Invalid regular expression: /*/: Nothing to repeat\",\"step\":\"Se73DhAs5\"}",
    "event": { "name": "kustomer.customer.update", "data": { "type": "customer", "id": "5e83c3a4d95b7e0012dc9711", "attributes": { … } } },
    "meta": {
      "context": "{\"order\":[\"1\",\"tNG_FZugW\",\"Se73DhAs5\"],\"steps\":{\"1\":{\"name\":\"kustomer.customer.update\",\"output\":{…}},…}}",
      "attempt": 1,
      "retry": false,
      "workflowRev": 27
    }
  }
}
Process attributes
errorstring (JSON)
eventobject
meta.contextstring (JSON)
meta.workflowRevnumber
statusstring

error and meta.context are strings, so parse them before reading. This script prints a one-line summary per failure:

const base = 'https://acme.api.kustomerapp.com'
const res = await fetch(`${base}/v1/workflows/${process.env.WORKFLOW_ID}/processes?pageSize=50`, {
  headers: { Authorization: `Bearer ${process.env.KUSTOMER_API_KEY}` },
})
const { data } = await res.json()

for (const p of data) {
  const error = JSON.parse(p.attributes.error ?? '{}')
  const context = JSON.parse(p.attributes.meta?.context ?? '{}')
  console.log(
    p.attributes.createdAt,
    `rev ${p.attributes.meta?.workflowRev}`,
    `${p.attributes.event?.name} ${p.attributes.event?.data?.id}`,
    `path ${(context.order ?? []).join(' → ')}`,
    `failed at ${error.step}: ${error.message}`,
  )
}

Common errors

Error messageCause and fix
next step not foundA transition's target doesn't match any step id. Check for renamed or deleted steps
operation <op> not supportedA condition uses an op that doesn't exist, such as in. See operators
trigger <eventName> not foundThe trigger's event isn't available, for example because the app that provides it was uninstalled
Missing param uri or Missing param methodA REST step's URL or method resolved to nothing. Usually a reference to a field that doesn't exist
Missing param regex or Missing param testStringA regex step's pattern or input resolved to nothing
runAt type must be one of absolute or relative, invalid runAt valueFix the Schedule a Workflow step's runAt. See Schedule a workflow
Payload too large to schedule workflowThe scheduled workflow's inputs are too big. Pass IDs instead of whole records
Method must be one of post, get, patch, put, or deleteFix the REST step's method
Invalid url protocol, DNS failure for …, Bad IP address for …, IPv6 hostname … not supportedThe URL breaks the REST step's rules: it isn't http/https, doesn't resolve, or points at a private or reserved address
Unescaped characters in request URLA value with spaces or special characters went into a URL. Wrap it with {{{uriEncode …}}}
Invalid regular expressionFix the regex step's pattern. Remember to escape backslashes in JSON ("\\d+")
A Kustomer API error, such as a validation title and detailA Kustomer action rejected its input: a missing required field, the wrong type, or an ID that belongs to another kind of record. The request is sent even when a required input is missing or empty (0, false and "" count as empty). Compare the step's input in the logs with the action's inputs

REST steps that get an error status from your service don't appear here: they succeed, and your transitions handle the status. See Handle responses and failures.

Errors when you save

Some problems are caught when you save rather than when the workflow runs. The most common is a loop: Step with ID <id> transitions to a previous step with ID <workflowId>:<target>, shown on the builder's canvas as "Cycle detected". Others include a duplicate name (409), nested root meta, and duplicate transitions. The full list is in Validate before you save.

When something runs twice

A run can repeat work for two reasons:

  • A system retry. When a Kustomer action gets a 5xx, or the platform has a temporary problem, the run starts again from step 1. Every step before the failure runs again, including creates, notes and REST calls. Make those steps safe to repeat: look up before you create, prefer Add Tags over replacing a tag list, and make your own endpoints idempotent. These retries don't appear in View errors.
  • The workflow triggered itself. An update trigger fires again for the workflow's own change. Guard it with a condition on changes, as described in Workflows.

When nothing happens

Work down this list. Most "it didn't run" reports stop at one of the first four items.

  • Enabled? Check the toggle or enabled in the JSON.
  • Waited a minute? New and changed workflows take about 60 seconds to start matching.
  • Right trigger? A new message fires kustomer.message.create and also kustomer.conversation.update. Make sure you picked the event that actually happens.
  • First condition matched? Open the run in View Logs. A run that stops after the trigger means no trigger transition matched. Look at step 1's output and compare it with the condition, paying attention to types ("4" vs 4), IDs vs names (tags and users are IDs), and changes paths.
  • Branch order? The first matching transition wins. A broad condition before a specific one swallows its runs. In the builder, that's the leftmost branch.
  • Empty values? A param or condition that comes out empty often references a variable by name instead of ID ({{{variables.apiKey}}} renders nothing), uses a step's position number instead of its ID, or reads callable inputs at /#steps.1.inputs.<name> instead of /#steps.1.<name>.
  • Saved, or only edited? Canvas changes don't apply until you Save, and Edit workflow JSON shows the last saved version. Changes then take about a minute to reach new runs.
  • Replaced? Another enabled workflow with replaces set to this workflow's ID stops it running.
  • Rate limited? Events over your org's workflow limit are skipped, not queued. Look for bursts, such as bulk imports.
  • Did it run and then get undone? Another workflow or an integration may be overwriting the change. Check the record's timeline.

Test safely

  • Gate on a test marker. While building, make the trigger's first condition require a tag such as wf-test (contains [/#steps.1.tags, "<tagId>"]). Only your test conversations run the workflow. Remove the gate when you go live.
  • Use a sandbox org for anything that writes data, sends requests to partners or could loop.
  • Watch for loops. A run count that climbs without new activity means the workflow is triggering itself. Disable it, then add a changes guard as described in Workflows.
  • Version your JSON. Keep workflow JSON in source control so you can diff a revision that broke something against the last good one. Save it from GET /v1/workflows/{id} rather than Export JSON, which leaves out response, enabled and logging. meta.workflowRev on each failure tells you which revision ran, and the builder's version picker opens the 30 most recent versions read-only.
  • Add error cases in JSON. The classic builder has no error-case editor. Use Edit workflow JSON or the API, as described in Handle errors.