> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Gating actions on exceptions

> Configure task template actions to disable approve and accept buttons until open data exceptions on critical taxon paths are resolved by the reviewer.

Validation rules on a Data Definition produce **data exceptions** when the rule fails. Exceptions stay open until a reviewer fixes the underlying value, marks the exception resolved, or marks it as overridden. A well-built task template uses those exceptions to drive the action toolbar — a reviewer cannot click **Approve** while the data they're approving is broken.

This recipe walks through the two flavours of the gate: *any open exception* and *open exceptions only on specific attribute paths*.

## The problem

A naive task template ships with an `Approve` action that always appears enabled. Reviewers can click it whenever they want, regardless of whether their open exceptions actually got fixed. The task transitions to `approved`, the activity plan moves on, and a downstream system gets bad data.

## The pattern

Two action properties control the gate:

| Property                                | Type             | Effect                                                                                                                                                               |
| --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onlyEnabledIfNoOpenExceptions`         | boolean          | Disable the action while **any** open exception exists on the task.                                                                                                  |
| `onlyEnabledIfNoOpenExceptionsForPaths` | `TaxonPathRef[]` | Disable the action while open exceptions exist on **any** of the listed taxon paths. Other open exceptions are ignored. Each entry is `{ taxonomySlug, taxonPath }`. |

Both live under `metadata.actions[].properties` in the task template YAML. They are evaluated in the UI against the current document's exception set whenever it changes — there is no extra round trip to the server.

<Tip>
  Use `onlyEnabledIfNoOpenExceptionsForPaths` when only some of the exceptions matter for the action. A reviewer might be allowed to send a document for re-extraction while a low-priority field is still flagged, but should never be allowed to approve a final invoice while the total line is in exception.
</Tip>

<Tip>
  The action editor in Studio renders `onlyEnabledIfNoOpenExceptionsForPaths` as a polished picker with taxonomy filtering, path search, group-taxon support, and a custom-path fallback for paths not in any bound taxonomy — no need to type slugs by hand.
</Tip>

### Block any open exception

The simplest gate. If anything is broken anywhere in the document, the button is disabled.

```yaml theme={null}
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptions: true
```

### Block only on specific taxon paths

When some attributes are critical and others are not, list the critical paths. Exceptions on any other field stop being a blocker.

```yaml theme={null}
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptionsForPaths:
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/invoice_number }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/total_amount }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/vendor_name }
```

The action is disabled while *any* of `invoice_number`, `total_amount`, or `vendor_name` has an open exception. A complaint about, say, `invoice/notes` is treated as advisory and does not block the button.

<Note>
  The path is the full taxon path as it appears in the Data Definition (parent group plus child name, separated by `/`). Use the same path you would use in a formula or selection-option expression.
</Note>

<Note>
  The legacy plain-string form (`["invoice/invoice_number", "invoice/total_amount"]`) is still accepted by the platform — entries are normalized to `{ taxonomySlug: "", taxonPath: "..." }` at runtime — but the object form is preferred and is what the Studio editor saves. Mixing both forms in the same list is supported during a migration.
</Note>

## Pairing with a "Reject" action

Reviewers usually need an escape hatch. A `Reject` button that *does not* check for exceptions lets them route a hopelessly broken document to a different team without first fixing every field by hand.

```yaml theme={null}
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptionsForPaths:
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/invoice_number }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/total_amount }

    - uuid: reject-action
      type: reject
      label: "Reject"
      properties:
        targetStatus: rejected
        statusSlug: rejected
        icon: close
        color: red
        keybind: "r"
        # No exception gate — reviewer can always reject.
```

In an [activity plan](/guides/activity-plans/create-task-steps) the next step can branch on which action was clicked, so the rejected document can be routed to a remediation queue without ever mixing into the approved-document flow.

## Recipe summary

1. Add `validationRules` to the Data Definition for every field that must be clean before approval. See [Validation and Conditional Formatting](/guides/data-definitions/validation-and-conditional-formatting).
2. On the approve action in the task template, set `onlyEnabledIfNoOpenExceptionsForPaths` to the list of paths you actually care about.
3. Keep the reject action ungated so a reviewer can always escape.
4. Test by raising an exception on a non-listed path — the approve button must stay enabled.

## Next: take ownership

Gating the action keeps bad data from being approved. The next recipe — [Take-ownership pattern](/guides/task-templates/take-ownership-pattern) — keeps good data from being silently *un*-approved by an AI agent or event subscription that runs after the reviewer has already accepted it.
