---
title: "Using stacks to identify and manage recurring issues"
slug: "using-stacks-to-identify-and-manage-recurring-issues"
updated: 2024-10-02T11:54:52Z
published: 2024-10-02T11:54:52Z
canonical: "support.lusid.com/using-stacks-to-identify-and-manage-recurring-issues"
---

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

# Using stacks to identify and manage recurring issues

You can define a stacking key within a [task definition](/v1/docs/how-do-i-create-a-task-definition) to populate a stacking key field for any exception [tasks](/v1/docs/how-do-i-create-a-task) it creates. For example, if you have a data quality check workflow containing a worker that creates exception child tasks, you can ensure recurring exceptions join a *stack*. You can then monitor and resolve multiple instances of the same issue together.

Let's imagine you want to model the following data quality check workflow ([created in this tutorial](/v1/docs/setting-up-a-data-quality-control-to-check-new-pricing-data-for-outliers)) in a task definition:

1. A parent task worker imports quotes from a new file in Drive.
2. A child task worker checks the quotes for outliers.
3. The worker creates an exception child task for each quote outlier.

When creating (or updating) your task definition, you can populate the `mapStackingKeyFrom` field in an [action](/v1/docs/using-actions-to-run-workers-create-child-tasks-and-trigger-parent-tasks) to automatically set a stacking key when a new exception task is created.

For example, you could pass in the following as part of your task definition to set the stacking key value to a Client Internal Instrument ID the exception relates to. LUSID can then group all exceptions for a certain instrument together:

```json
...
"actions": [
  {
    "name": "quote-outliers-check-worker",
    "actionDetails" : {
      "type": "RunWorker",
      "workerId": {
        "scope": "Finbourne-Examples",
        "code": "Check-Quotes-For-Iqr-Outliers"
      },
      ...
      "childTaskConfigurations": [
        {
          "taskDefinitionId": {
            "scope": "Finbourne-Examples",
            "code": "Quote-Outliers-Exception"  
          },
          "initialTrigger": "start",
          "childTaskFields": {
            "clientInternal": {  "mapFrom": "ClientInternal" },
            "lowerLimit": {  "mapFrom": "LowerLimit" },
            "upperLimit": {  "mapFrom": "UpperLimit" },
            "price": {  "mapFrom": "Price" },
            "priceDate": {  "mapFrom": "PriceDate" },
          },
          "mapStackingKeyFrom": "ClientInternal"
        }
      ]
    }
  },
  ...
```

You can tailor the stacking key mapping to best suit exceptions you might anticipate in your data quality check. You might map the stacking key value from a particular field to group exceptions by data vendor, or by the filename the quotes were imported from. You could then track and automatically close a stack when the lead exception from that data vendor or file is resolved.

Note you can currently use the `mapStackingKeyFrom` field in the following [action types](/v1/docs/using-actions-to-run-workers-create-child-tasks-and-trigger-parent-tasks):

- `RunWorker`
- `CreateChildTasks`

### When does a stack open?

When a new task is created to check for quote outliers and this generates an exception task for an outlier quote, the Workflow Service assesses the stacking key value (in this case, a Client Internal ID) to determine what to do next:

- If the stacking key value does not match an existing open stack, nothing happens for now.
- If the stacking key value matches the value of another task's stacking key (of the same task definition), a *stack* opens:
  - The existing task becomes the stack *leader*.
  - The newly-created task becomes a stack *member*.

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/cd65717d-b042-4564-b01b-d61c0203a537.png)

### How do I view my stacks?

You can view a task's stacking key in the [LUSID web app](https://www.lusid.com/app/home) by navigating from the top left menu to **Workflow Service > Dashboard**.

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/e05c8101-ff87-4111-b772-dc471a4654fe.png)

A stack icon indicates a task is part of a stack and whether the task is the stack *leader* or a *member*:

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/18b8c694-fe2a-46fa-99b8-f7fe8d0c2052.png)

You can select the stacking key value for a task to view more stack information, including all other tasks within the stack.

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/4beebd4a-50c0-49a7-8184-666edf69a410.png)

### When does a stack close?

A stack remains open until the *leader* task reaches a terminal state.

Currently, you can reference stacks in a [guard condition](/v1/docs/using-guards-to-add-conditions-to-workflow-state-transitions) to customise how your workflow handles tasks within a stack. For example:

- To prevent people from performing duplicate work on *member* tasks, you might specify a guard condition of `stack.membershipType neq 'Member' or stack.membershipType not exists` to prevent a task transition from occurring if the child task is a *member* within a stack.
- You might specify a guard condition of `"childTasks all (state eq 'Resolved' OR stack.membershipType eq 'Member')"` to prevent a task transition from occurring unless all child tasks are either resolved or accounted for in a stack as a *member*.

In the future, it will be possible for *member* tasks to be automatically resolved when the stack *leader* is resolved.

### What happens if a stacking key value changes or is removed?

The following table provides information on stack behaviour in various scenarios:

| **Scenario** | **Effect on original stack** | **Effect on task** |
| --- | --- | --- |
| `stackingKey` value changes for an existing task | If task is not part of a stack | N/A | Task assessed for entry into a new or existing stack |
| If task is part of a stack | Stack is reassessed for *leader*/*member* | Task leaves stack Reassessed for entry into new or existing stack |
| Task is deleted | If task is not part of a stack | N/A | N/A |
| If task is part of a stack | Stack is reassessed for *leader*/*member* | Task leaves stack |
| `stackingKey` set to `null` | If task is not part of a stack | N/A | N/A |
| If task is part of a stack | Stack is reassessed for *leader*/*member* | Task leaves stack |

A series of one of more task definitions and workers that combine to complete a process.

Units of functionality in the Workflow Service which can access LUSID data. Called by tasks, workers take input parameters mapped from the fields of a task, and return results which can be mapped to a task definition. Worker status can be used to trigger a parent task automatically.

A condition a task can exist in, for example **Pending**, **In progress**, or **Complete**. State names are customisable and can be defined in a task definition.

An operational condition which must be met for a state transition to succeed in the Workflow Service. For example, all child tasks are in the state

**Complete**

.
