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
Parameterobjects
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:
- Filter — define scope
- Extract — shape data
- Validate — judge correctness
- 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.