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

> ## Agent Instructions
> These docs contain multiple Speckle product experiences. For Speckle 2026.9, prefer /next/ pages for the topics and changes they cover. The navigation label Current does not override this version-specific precedence.
> Coverage under /next/ is incremental. Use Current documentation for unchanged topics and when a /next/ page says coverage is unavailable or explicitly refers you to Current. Do not infer a feature was removed from a missing page.
> Read the page-specific documentation status, applicability, affected guidance and replacement links in agent-only content. Impacted, changed and superseded apply only to the stated scope; they do not mean the entire feature is deprecated. Historical connector guides apply only to the legacy connector described.
> Match guidance to the customer's deployment version, model data format and connector. Respect plan, permission and compatibility restrictions. If an unknown version or data format changes the answer, ask a focused clarification; do not infer deployment version from the date alone.

# Checks

> Author and run Validation Checks with WHERE/CHECK logic in Data Validation.

Documentation status: changed for the changes in Speckle 2026.9 (from 2026-09).

Affected guidance: 2026.9 validation scope, property paths, relations, and removal of project standards.

For these changes, read [2026.9 guidance](/next/analytics/data-validation/overview).

For Speckle 2026.9, prefer the linked guidance only for the affected topics. This page remains applicable to earlier experiences and unchanged guidance. Do not treat the whole page or feature as deprecated.

<Warning>
  Current limitation:

  After you save a check, you can edit its name and description, or delete it. Tracked
  models, rules, predicates, and trigger mode stay frozen. For different behaviour, create a
  new check.
</Warning>

Use this page for **Validation Check** authoring and execution.

<Info>
  Checks are executable validation definitions tied to tracked models. For reusable templates in the
  current product, use [Standards](/analytics/data-validation/standards).
</Info>

<Note>
  2026.9 does not include project standards. See [Data Validation in
  2026.9](/next/analytics/data-validation/overview#project-standards).
</Note>

<Note>
  Checks can be defined and run against models in a project (plan caps apply). Editing an
  existing check is limited to name and description until model scope, rules, and trigger
  mode become editable.

  Feedback welcome on expected **versioning behavior** for checks (for example: mutable
  checks vs immutable versions or forks).
</Note>

## Run a first check

Use **Run check** from the project sidebar when you want to test rule logic on
real project data.

<Steps>
  <Step title="Load preview model">
    Empty first screen until a preview model loads. Load preview to unlock starters and pick
    model/version context first.
  </Step>

  <Step title="Draft and preview rules">
    Define `WHERE` / `CHECK`; preview (**Run Preview** or `Ctrl+Enter` / `Cmd+Enter`) to validate
    logic before save.
  </Step>

  <Step title="Review first output">First preview yields one aggregate plus one row per rule.</Step>

  <Step title="Refine before save">
    Preview is ephemeral, so tune scope before save. Edited rules prompt a rerun so displayed
    numbers stay trusted.
  </Step>

  <Step title="Handle large-model behavior">
    Large models may skip the 3D pane; assertions still evaluate when preview is unloaded.
  </Step>

  <Step title="Confirm persistence">
    Done when **Checks** shows the new card, which confirms persistence.
  </Step>
</Steps>

## Build a check with many rules

One topical check can own many rules (e.g. fire ratings on walls/doors/windows) so failures
stay rule-level inspectable—use **Add rule**, one requirement per rule, per-rule **Run**,
duplicate when scopes match.

## Operate checks over time

Saving locks rules to tracked models—later versions rerun the same predicates without redoing ad-hoc spreadsheets.

Manual vs auto trigger matches how tightly you gate runs. Charts need repeated runs—the
first save is often your baseline-only pass. Expanded rule rows expose `WHERE` → `CHECK`
counts when a filter swallowed your elements prematurely.

Layouts: [What you see on the
page](/analytics/data-validation/viewing-results#what-you-see-on-the-page). Ordering:
[Practical review
flow](/analytics/data-validation/viewing-results#practical-review-flow).

Save the check after scope is final, then read combined scores on
[Viewing Results](/analytics/data-validation/viewing-results).

First visit to results can lag when many rules, models, or deep history enqueue work.

## Rule structure in checks

Each rule is filters plus one assertion.

| Component | Description |
| - | - |
| `WHERE` | Filter scope of objects evaluated by the rule |
| `AND` | Optional additional filters within the same scope |
| `CHECK` | Final validation assertion |
| Property path | Target property (`category`, `baseline.length`, `parameters.Width.value`) |
| Predicate | Comparison operator (see [Predicates and matching](#predicates-and-matching)) |
| Value | Reference value for the predicate |
| Report severity | `error` or `info` (`info` does not drive the overall check score) |
| Message | Human-facing explanation for failed outcomes |

## Default scope

Default filter: `speckle_type` **Contains** `DataObject`, the connector-produced base BIM
bucket (Revit, IFC, ...). `DataObject` is the base type Speckle connectors produce, so most BIM
objects match it. Narrow with category/type/parameters—dropping `DataObject` widens noise risk.

<Warning>One terminal `CHECK` per rule—extra assertions belong in extra rules.</Warning>

## Thresholds and status

Rates map through thresholds. You set a global pass (and optional warn) threshold when saving,
and you can override thresholds per rule in authoring.

| Setting | Effect |
| - | - |
| Pass threshold | Minimum pass-rate for `PASS`. |
| Warn threshold | Optional lower bound yielding `WARN` between warn and pass. |
| No warn threshold | Below pass ⇒ `FAIL` (no intermediate `WARN`). |

Statuses: **`PASS`** (≥ pass), **`WARN`** (between thresholds when warn is set), **`FAIL`**
(under thresholds), **`PENDING`** (evaluation not finished).

Only **`error`** severity rules contribute to the overall check score. **`info`** rules still
evaluate and appear in results, but they do not change the aggregate pass rate.

Interpret outcomes on [Viewing Results](/analytics/data-validation/viewing-results).

## Predicates and matching

The operator dropdown lists every authorable predicate. The UI does not grey operators by
property type—pick a value shape that matches the property you are testing (text, number, or
boolean). Booleans compare as Equals with `true` or `false`.

### Operator catalog

| Operator | Typical value | Behaviour |
| - | - | - |
| Equals | text, number, or boolean | Exact equality on the property value |
| Equals property | another property path | Path-to-path equality |
| Equals template | template with `{{token}}` bindings | Build expected text from other paths; exact or regex mode |
| Not equals | text, number, or boolean | Value must differ |
| Greater than | number | Strict `>` |
| At least | number | `≥` (tolerance can widen the lower bound) |
| Less than | number | Strict `<` |
| At most | number | `≤` (tolerance can widen the upper bound) |
| In list | one or more text or number values | Value must be one of the listed items |
| Between | min and max numbers | Inclusive range (`≥ min` and `≤ max`) |
| Contains | text substring | Substring match (wildcards in the needle are literal, not patterns) |
| Matches | wildcard or regex pattern | Wildcard by default; toggle `.*` for regex (see below) |
| Exists | *(none)* | Property path is present on the object |

### Matching details

**Matches (wildcard):** `*` and `%` match any character run; `?` matches one character.
Matching is case-sensitive.

**Matches (regex):** turn on the `.*` toggle to use a regular expression. You can enter a
plain pattern, or a `/pattern/i` literal for case-insensitive matching. Lookahead,
lookbehind, and backreferences are not supported.

Regex mode requires a **full-string match**. The pattern must account for the entire value, not
only the prefix you are asserting. `^(Wall|Door)` matches only the exact strings "Wall" and
"Door". Use `^(Wall|Door).*` to match values that start with those prefixes, or use wildcard
mode (`Wall*`) instead. See [Regex mode](/analytics/dashboards/filters#regex-mode) for more
pattern examples.

**Equals template:** bind `{{token}}` placeholders to other property paths. Use exact mode
to require the concatenated value, or regex mode (same `.*` toggle and the same full-string
match) when the template is a pattern.

**Contains** is substring search only. Prefer **Matches** when you need wildcards or regex.

### Numeric tolerance

Optional per-condition **Tolerance** sets decimal places `N` (ε = 10^-N). It applies to
numeric **Equals**, **Equals property**, **At least**, **At most**, and **Between**. It
does not apply to **Greater than**, **Less than**, **Not equals**, list/text operators, or
**Exists**.

### Property paths

Pick paths from the path picker after a preview model loads so value suggestions come from
real data. Common shapes:

* `category`
* `name`
* `baseline.length`
* `parameters.Width.value`

### Short examples

* Fire rating present: `WHERE` category Equals `Walls`, `CHECK` fire-rating path **Exists**
  (or **Equals** a required rating string).
* Width band: `CHECK` `parameters.Width.value` **Between** `100` and `300`, with tolerance if
  units are noisy.
* Naming convention: `CHECK` `name` **Matches** `W-*`. In regex mode use `^W-.*` so characters
  after the prefix still match.
* Consistency: `CHECK` one path **Equals property** against another path on the same object.

## Run a check on every submission automatically

For the specific pattern of validating incoming consultant or subcontractor models against your
standard at every milestone — author once, set **auto** trigger, and stop relying on someone to
remember to run it — see [Validate incoming models
automatically](/next/workflows/validate-incoming-models-automatically).

## Best practices

Tighten `WHERE` first so broad scopes do not flood triage.

Write descriptive **Message** text so fix owners can act without extra clarification.

Run preview before save so you catch false positives before history is recorded.

## FAQ

<AccordionGroup>
  <Accordion title="Can I create a check from a standard?">
    Yes—pick models and triggers after choosing the standard as the base.
  </Accordion>

  <Accordion title="How do I know a check is too strict?">
    Noise usually means tighten `WHERE`, tune predicates, or downgrade severity to `info`.
  </Accordion>

  <Accordion title="What happens to check results when a tracked model is deleted?">
    Existing results stay in history because they store the evaluated model/version ids from run
    time. The deleted model no longer appears in live scope, so future runs exclude it.
  </Accordion>

  <Accordion title="Can rules inside one check be reordered?">
    Rule order follows how rules were authored and saved. Reordering is not supported yet, so
    duplicate or recreate is the fallback when order matters for review.
  </Accordion>

  <Accordion title="What is the difference between preview and saving a check?">
    Preview runs against the current session model/version and is not persisted after you leave.
    Saving persists tracked models, trigger mode, thresholds, and result history.
  </Accordion>

  <Accordion title="How do I recover when a version update spikes unexpected failures?">
    First confirm the result used the model/version you expected, then inspect failing rules for
    missing or changed properties in the new version. If needed, create a narrower replacement check
    for debug, export BCF for issue handoff, then keep the replacement once root cause is clear.
  </Accordion>

  <Accordion title="Why does a Matches regex check fail values that start with my pattern?">
    Regex mode matches the entire value, not a prefix. `^(Wall|Door)` matches only those exact
    strings, so values such as `Wall_01` fail. Append `.*` (`^(Wall|Door).*`) or use wildcard mode
    (`Wall*`). See [Predicates and matching](#predicates-and-matching).
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.