Decision run outcomes

Every call to a decision endpoint ends in one of four ways. Knowing which one you are looking at tells you whether you have a decision, and what to do when you do not.

1. A decision was returned

The endpoint answers with HTTP 200 and the decision flow's output. The run appears in the execution log with the status OK. This is the normal case, including runs where a rule deliberately declined or referred the application.

2. A decision was returned, but something inside it reported a problem

Some problems belong to one part of the flow rather than to the decision as a whole. The clearest example is a data source that did not answer, answered with an error, or could not use its credential.

In that case the run continues. The step marks its own result as failed and the rest of the flow carries on, so your rules can see the failure and decide what to do about it — fall back to another provider, apply a conservative score, or route the application to manual review. This is deliberate: an outage at one bureau should not take down every decision you make.

You will see this in the run detail as an error on that step, with a short reason such as:

Reason on the stepWhat it meansWhat to do
Credential unavailableThe credential this data source uses is no longer usable. It was deleted or switched off, or a new release has not reached the execution node yet.Check the credential under Credentials. If it was deleted, create it again and re-save the data source. Note that deleting a credential that is still in use warns you first.
Endpoint blockedThe address configured for this data source is not one we are willing to call.Check the endpoint URL on the data source.
Network or HTTP errorThe provider did not answer, timed out, or answered with an error.Usually the provider's side. Retry, and check the provider's status.

Because these do not stop the run, a flow that never checks them will silently treat "no data" as "no hit". If a bureau result matters to your outcome, add a rule that branches on the step's error.

3. The run stopped early at a fork

A fork sends the run down exactly one branch. When none of its branches match, there is no branch to follow and the run ends at the fork. The endpoint still answers with HTTP 200 and everything computed up to that point, but the steps after the fork never ran, so the fields they would have written are simply absent.

This is the quietest of the outcomes, because a short answer looks like a valid one. You can recognise it in the response:

  • the fork's own output carries "__status": "no_branch_matched", under output.<name of the fork step>
  • a __forks_unmatched list at the top level names every fork it happened on

When you test a release with lineage recording turned on, the explainability view flags this for you: a warning at the top of the run, and the same warning on the fork step itself. You do not have to read the raw response to spot it.

Two things cause it.

CauseExample
A gap between the branch conditionsThe branches cover 0 to 30 and 40 and above. The value was 35, so nothing matched.
A missing attributeA fork condition tests a value the data does not contain. A missing number counts as zero, so it fails every branch that asks for a higher value, and the fork can be left with no branch at all.

The fix is the same for both: give every fork a final branch that always matches, using the any value condition, and point it at your safe default, usually a manual review. Branches are tried in order and the first match wins, so a catch-all placed last only takes the runs nothing else claimed. See Fork.

4. The run did not complete

The endpoint answers with HTTP 500 and a reason. The body still contains everything the flow computed up to the point where it stopped, which is what makes the problem diagnosable, but it is not a decision and must not be processed as one.

This is on purpose. A decision assembled from a half-finished run looks exactly like a real one, and there is no way for your system to tell them apart afterwards. We would rather fail loudly than hand you an answer we do not stand behind.

ReasonWhat it meansWhat to do
step_failedA step could not complete its work. The response names the step, and the run stopped there rather than continuing on partial data.Open the run in the execution log. The named step is marked failed. Most often the step received data in a shape it did not expect, for example a list where a single value was configured. Check the attribute mappings on that step against the data you actually send.
unserialisable_resultThe finished result contained a value that cannot be represented in a response. The two usual causes are a number far outside the range ordinary numbers can express, and text that is not valid Unicode.The response lists the affected fields under __repaired_values. Check those fields first: if one of them is your score or amount, the run is not usable; if it is an incidental text field, you are looking at a data-quality problem in one source system. An extreme number usually means an amount arrived in an unexpected unit or format. Invalid text usually means a source system is sending a legacy character encoding rather than UTF-8.
Malformed JSONThe request body could not be read at all.Check that the request is valid JSON. Very deeply nested structures are also rejected here.

A note on detailed tracing

Detailed tracing keeps a copy of the data after every step so you can replay how a decision was built. It has a size limit, and the limit applies to tracing, never to deciding.

When the data is too large to trace, whether it arrived that way or grew mid-run because a provider returned something very large, tracing is switched off and the decision runs to the end as normal. You get your decision, with a __lineage_omitted note in the response saying where tracing stopped and why.

A request is never turned away for being too large to trace. You have already paid to acquire that applicant by the time the request reaches us, and a diagnostic nobody is waiting for is not worth a decision.

The partial trace is discarded rather than returned. A trace covering the first four steps of a nine step run looks exactly like a complete trace of a four step run, and nobody reading it later could tell the difference. A trace you receive is always complete; if it is missing, the response says so.

What to give support

Every run has a request identifier, shown in the execution log and returned with error responses. Quote it. It is the single thread that ties your request to everything recorded on our side, and with it a failed run can be traced without you having to send us the payload.

Keeping runs healthy

A few habits prevent most of the failures above.

  • Send values in the shape the flow expects. A field configured as a single amount should not sometimes arrive as a list. Testing a release with real sample payloads catches this before production does.
  • Send text as UTF-8. This matters most for names and addresses with diacritics, which are common in Central European data.
  • Do not delete a credential that is still referenced. The platform tells you what would break before it lets you.
  • Check step errors in your rules where the answer depends on external data.
  • Give every fork a catch-all branch. A fork that matches nothing ends the run where it stands, without saying so.
  • Watch the execution log after a release. A change in the shape of incoming data shows up there first.