Skip to content

Common first mistakes (and how to avoid them)

This page collects the most common mistakes people make when writing their first DAQS rules.

If something “looks right” but behaves strangely, chances are it falls into one of these categories.


Mistake 1 — Filtering where the data does not live

The problem

New users often filter objects based on assumptions instead of the actual data model.

Example:

$[type = "FamilyInstance" and values.category.label = "OST_Doors"]

This looks logical — but it is wrong.

Why this fails

In DAQS (and in the Revit API):

  • Category data lives on the FamilySymbol
  • Instances only reference their type via parent.id

Filtering instances by category directly leads to:

  • Inconsistent results
  • Missing elements
  • Fragile rules that break silently

The correct approach

Always filter types first, then instances:

$symbols := $[
  type = "FamilySymbol"
  and values.category.label = "OST_Doors"
].id;

$[
  type = "FamilyInstance"
  and parent.id in $symbols
]

Mistake 2 — Using UI names instead of API identifiers

The problem

Using Revit UI labels in rules:

values.category.name = "Doors"

Why this is wrong

UI names:

  • Are language-dependent
  • Can be renamed
  • Are not stable identifiers

DAQS rules must be language-independent.

The correct approach

Always use API labels:

values.category.label = "OST_Doors"

Mistake 3 — Hiding missing data in the filter

The problem

Filtering out missing values instead of reporting them:

$[
  type = "FamilySymbol"
  and values.assemblyCode != null
]

Why this is dangerous

This silently removes:

  • Elements with missing data
  • Elements that should fail validation

The result:

“No errors found” — while the model is actually incomplete.

The correct approach

Use filters to define scope, not correctness.

Let validation handle missing or invalid values.


Mistake 4 — Treating classification as instance data

The problem

Trying to read classification data from instances:

values.assemblyCode

On a FamilyInstance.

Why this fails

Classification data such as:

  • Assembly Code
  • OmniClass
  • Uniclass

Belongs to the type, not the instance.

The correct mental model

Data type Lives on
Category FamilySymbol
Assembly Code FamilySymbol
Type parameters FamilySymbol
Location / Level FamilyInstance
Instance parameters FamilyInstance

If the data is on the type → filter types first.


Mistake 5 — Hardcoding shared-parameter GUIDs everywhere

The problem

Using raw GUIDs directly in rules:

$lookup(values, "p_beca98b3-5207-4cde-a26b-7e9797c4eb26")

Why this is fragile

  • GUIDs are unreadable
  • Easy to mistype
  • No confirmation the parameter exists in the project
  • Impossible to review at scale

The correct approach

Always:

  • Centralise GUIDs
  • Use logical parameter names
  • Resolve metadata via Parameter objects

This makes rules:

  • Safer
  • Reviewable
  • Model-aware

Mistake 6 — Assuming a parameter exists because it “should”

The problem

Writing rules that assume project configuration is correct.

Reality check:

Projects are often misconfigured.

What goes wrong

You cannot distinguish between:

  • Parameter does not exist in the project
  • Parameter exists but is not bound
  • Parameter exists but has no value

The correct approach

Always separate:

  • Parameter existence (project-level)
  • Parameter binding (element-level)
  • Parameter value (content-level)

Defensive rules are not pessimistic — they are realistic.


Mistake 7 — Overloading one rule with too much logic

The problem

Trying to do everything in one rule:

  • Filtering
  • Data extraction
  • Validation
  • Error formatting

Why this fails

  • Rules become unreadable
  • Debugging becomes impossible
  • Review takes too long
  • Small changes break unrelated logic

The correct approach

Think in layers:

  1. Filter — define scope
  2. Extract — shape data
  3. Validate — judge correctness
  4. Report — explain clearly

If a rule feels complicated, one of these layers is probably mixed in the wrong place.


Mistake 8 — Copying advanced patterns too early

The problem

Jumping straight to:

  • Symbol indexing
  • Regex-heavy filters
  • Shared-parameter helpers

Without understanding the basics.

Why this hurts

  • Rules “work” but are not understood
  • Small changes break everything
  • Users cannot explain what their rule does

The correct approach

Use advanced patterns only when:

  • The simple version is clear
  • The limitation is understood
  • The complexity is justified

Power patterns are tools — not shortcuts.


Final advice

When a rule behaves strangely, the cause is almost never JSONata syntax. It is almost always a wrong assumption about where data lives or what exists.

Slow down. Check the data shape. Then write the rule.