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

# Add custom validation

> How to add custom validation for limit structures, limits, and incidents in Atoti Limits, covering the default validation checks for each object type and how to extend or override individual validators and error handlers

This section describes how to create custom validators, validation errors, and validation error handlers in Atoti Limits.

[Limit structures](../../user-ref/datastore/limit-structures), [limits](../../user-ref/datastore/limits-store), and [incidents](../../user-ref/datastore/incident-store)
are validated whenever they are created or updated. The default implementations of these validation interfaces provide reasonable
checks to promote data quality, but you may wish to customize or extend these checks to suit your organization’s needs.

Implementing custom validation is not required, but it can be useful for enforcing business rules or data quality standards.
Additionally, any single component or combination of these components can be customized, and any components not customized will use default implementations.
For example, you could choose to implement a custom `ILimitValidator` but use `DefaultLimitStructureValidator` and `DefaultIncidentValidator`.
Alternatively, you could choose to implement a custom `IValidationErrorHandler` that overrides `DefaultValidationErrorHandler` in the default validators.

## A note on the default validation behavior

The default implementations of the validation interfaces are agnostic to the source of the data being validated. However,
there is different behavior for the initial load of limits via `ILimitsFileLoadingService` and limits loaded through
REST, like [file upload](../../user-ref/using-limits/create-limit/create-limit-upload). For the initial load of limits, the validation is non-blocking, meaning that the system
will proceed with publishing the valid limits even if some fail validation. When limits are loaded through REST, the
validation is atomic, meaning that the system will not publish any limits if even one fails validation.

This is because errors with limits in the initial load are likely to be addressed by an administrator/developer and
should not block business users. However, loading through the UI (file upload) is more likely to be done by a business
user and needs to have better enforcement of data integrity.

## Checks performed in the default validators

This section describes the validation performed by the default validators for limit structures, limits, and incidents.

### Default limit structure validation

<table><thead><tr><th>Field</th><th>Validation performed</th></tr></thead><tbody><tr><td>Structure ID</td><td>Value must be non-null, non-empty, and unique. This field is validated regardless of the ID being provided or generated.</td></tr><tr><td>Name</td><td>Value must be non-null, non-empty, and unique.</td></tr><tr><td>Server Name</td><td>Value must be a valid server name in the current list of connections to Atoti Limits.</td></tr><tr><td>Cube Name</td><td>Value must be a valid cube name in the current list of cubes for the specified server.</td></tr><tr><td>Measure Name</td><td>Value must be a valid measure name in the specified cube <strong>OR</strong> a calculated measure saved in the content server.</td></tr><tr><td>Scope Keys</td><td>Value must contain the name of at least one level, and all levels expressed must exist in the specified cube.</td></tr><tr><td>Polling Frequency</td><td>Value must be a valid PollingFrequency enum (<code>EOD</code> or <code>INTRADAY</code>).</td></tr><tr><td>KPI Type</td><td>Value must be either <code>Greater Than</code> or <code>Less Than</code>.</td></tr><tr><td>Limit Changes Workflow Parameters</td><td>If the value for <code>Limit Changes Workflow</code> is <code>StraightThrough</code> or not provided (will default to <code>StraightThrough</code>), this field can be null. For all other workflow types, this field must be a valid map containing at least one field+value pair.</td></tr></tbody></table>

### Default limit validation

<table><thead><tr><th>Field</th><th>Validation performed</th></tr></thead><tbody><tr><td>Limit ID</td><td>Value must be non-null, non-empty, and unique. This field is validated regardless of the ID being provided or generated.</td></tr><tr><td>Structure ID</td><td>Value must be a valid ID for an existing limit structure.</td></tr><tr><td>Scope</td><td>If the scope is aggregated (see <a href="../scopes/advanced-scopes">advanced scopes</a>), the structure this limit is being created on must not contain any live limits. Similarly, attempting to create a limit with any scope on a structure that contains an existing limit with an aggregated scope will result in a validation error.</td></tr><tr><td>Start Date</td><td>Value must be a valid date in ISO-8601 format (<code>yyyy-MM-dd</code>).</td></tr><tr><td>End Date</td><td>If provided, value must be a valid date in ISO-8601 format (<code>yyyy-MM-dd</code>) and must not fall before the <code>Start Date</code>.</td></tr><tr><td>Limit Type</td><td>Value must be a valid LimitType enum (<code>OFFICIAL</code> or <code>TEMPORARY</code>).</td></tr></tbody></table>

#### Limit overlapping date validation

The default limit validator also checks for overlapping dates between limits. Limits are considered to overlap if they
have the same `Structure ID`, `Scope`, and `LimitType` **AND** if there is even a single day of overlap between the
date ranges represented by each limit’s `Start Date` and `End Date`.

#### Temporary limit validation

In addition to the checks above, temporary limits require some extra validation:

* `End Date` must be provided. The overlapping date validation still applies to temporary limits.
* `Source Limit ID` must be provided and the value must be a valid ID for a limit with `Limit Type = OFFICIAL`.

### Default incident validation

<table><thead><tr><th>Field</th><th>Validation performed</th></tr></thead><tbody><tr><td>Incident ID</td><td>Value must be non-null, non-empty, and unique. This field is validated regardless of if the ID was provided or generated.</td></tr><tr><td>Limit ID</td><td>Value must be a valid ID for an existing limit.</td></tr></tbody></table>
