Validation Error Catalogue
Every error message loom check can emit, what triggers it, and how to fix it. Errors are reported with a dotted path identifying the offending node (e.g. fields[2].type).
Header errors
| Error | Trigger | Fix |
|---|---|---|
model: is required |
The model: key is missing |
Add a top-level model: <PascalCaseName> |
model: "<name>" must be PascalCase |
Model name is lowercase, snake_case, or has spaces | Rename to PascalCase: Customer, InvoiceItem |
label: is required |
Missing label: |
Add a human-readable label: |
icon: is required |
Missing icon: |
Add a Lucide icon name (users, file-text, tag, …) |
Fields errors
| Error | Trigger | Fix |
|---|---|---|
fields: must declare at least one field |
Empty fields: list |
Add at least one field |
fields[N].name: is required |
Field's name: missing |
Add a snake_case name: |
fields[N].name: "<name>" must be snake_case |
Name has uppercase or hyphens | Rename: companyName → company_name |
fields[N].name: duplicate field name "<name>" |
Two fields with the same name | Rename one |
fields[N].type: is required |
Field's type: missing |
Add a recognised type |
fields[N].type: "<type>" is not a recognised field type |
Typo in type | See Reference → Field Type Catalogue |
fields[N].options: field type "<t>" requires at least one option |
select/radio/multiselect with no options |
Add options: |
fields[N].options: field type "<t>" does not support options |
Field that isn't select/radio/multiselect has options |
Remove options: |
fields[N].options[M].value: is required |
Option missing value: |
Add value: |
fields[N].options[M].label: is required |
Option missing label: |
Add label: |
fields[N].target: link field requires a target model |
link without target: |
Add target: <PascalCaseModel> |
fields[N].target: field type "<t>" does not use target |
Non-link field with target: |
Remove target: |
fields[N].target: "<t>" must be PascalCase model name |
Target isn't PascalCase | Rename to PascalCase |
fields[N]: min (X) is greater than max (Y) |
Inverted range | Swap min/max |
Relationships errors
| Error | Trigger | Fix |
|---|---|---|
relationships[N].type: is required |
Missing type: |
Add type: has_many / belongs_to / many_to_many |
relationships[N].type: "<t>" is not a valid relationship type |
Typo | One of has_many, belongs_to, many_to_many |
relationships[N].target: is required |
Missing target: |
Add target Thread name |
relationships[N].target: "<t>" must be PascalCase model name |
Target isn't PascalCase | Rename |
relationships[N].through: many_to_many requires a 'through' join model |
M2M missing through | Add through: <PascalCaseJoinModel> |
relationships[N].through: through is only valid for many_to_many |
Non-M2M with through |
Remove |
Permissions errors
| Error | Trigger | Fix |
|---|---|---|
permissions[N].role: is required |
Missing role | Add role: <RoleName> |
permissions[N].can: must be "all" or a non-empty list of actions |
Empty can |
Use all or [read, create, ...] |
permissions[N].can[M]: "<action>" is not a valid action |
Typo | One of read, create, update, delete |
ListView / FormView errors
| Error | Trigger | Fix |
|---|---|---|
list_view.columns[N]: "<f>" is not a declared field |
Column references missing field | Fix the column name or declare the field |
list_view.filters[N]: "<f>" is not a declared field |
Same, for filters | |
list_view.default_sort: "<f>" is not a declared field |
Same, for default sort | |
list_view.sort_order: "<x>" must be "asc" or "desc" |
Bad sort order | Use asc or desc |
list_view.page_size: must be >= 0 |
Negative page size | Use a positive integer |
form_view.sections[N].columns: must be 1 or 2, got X |
Bad column count | 1 or 2 only |
form_view.sections[N].fields[M]: "<f>" is not a declared field |
Section references missing field | Fix |
form_view.related_lists[N].model: is required |
Missing related model | Add |
form_view.related_lists[N].model: "<m>" must be PascalCase model name |
Bad casing | Rename |
Hooks errors
| Error | Trigger | Fix |
|---|---|---|
hooks.<event>: "<name>" is not a valid Go function name |
Hook name has invalid chars | Use letters/digits/underscores, start with a letter |
Strict-mode YAML errors
loom check uses KnownFields(true), so any unrecognised key surfaces a YAML decode error like:
field requried not found in type schema.Field
The fix is always the same: correct the typo (requried → required).
See also
- Reference → Thread YAML Schema — what's allowed
- Getting Started → Quickstart — see the validator in action
← Previous
Lifecycle Hooks — before_save, after_save, before_delete, after_delete
Next →
Multi-tenancy
Was this article helpful?