1. Wrong operator names
and, or, neq, nin and == are rejected when you save. Use all, any, ne, not_in, eq.
2. Trusting what users can edit
- Compare values:
$auth.claims.planequalspro
plan is set by your server. A person can edit user_metadata. Use roles, permissions or private metadata (app_metadata), and mark attributes that grant things admin-only.
3. Null equals null
- Compare values:
$record.orgequals$auth.org
4. Forgetting the owner on server-created records
A secret-keycreate with no owner leaves owner_id empty. The owner rule never matches, so the person can’t see their own record. Set it explicitly.
5. A write left on “default”
An enabled action with no rule allows any signed-in user. Studio warns in amber. Choose a rule for every action you turn on.6. public on a write
Studio flags it in red: “Anyone on the internet… can add records.” Only a signup or contact form should be public, and then rate-limited.
7. list looser than get (or the other way)
People read records they can’t list by guessing ids, or see rows they can’t open. Use the same rule for both.
8. Protecting the UI instead of the data
delete rule is authenticated, anyone can call it. The rule is the lock.
9. A route that skips the owner check
A route withpermission:orders.pay doesn’t know the order is yours. The flow must load the order as the caller and check, or let the table’s rules do it (Routes).
10. Relying on a hidden column
A rule doesn’t hide columns. Anyone who can read the row can read all its columns (except write-only ones). Split the table or use write-only for secrets.11. Rules that depend on other tables
JSON can’t query another table. People write rules that assume it can. Copy the needed value onto the record, put it in the token, or check it in a flow. See Rules that need more data.12. Changing a shared named rule without testing
One edit changes every table that uses it. Test, or fork the rule first (Named rules).13. Expecting roles to apply instantly
Roles live in the token. A change arrives at the next refresh (minutes) or sign-in. End sessions to force it.14. Testing only as yourself
Your own account is the most permitted one. Test as a stranger, as a different team’s member, and as a visitor.15. Using not around missing data
None of ($record.status equals archived) passes records with no status. State what you allow instead.
16. Secrets in browsers
A secret key bypasses every rule. The browser build refuses to start with one; don’t override that.17. Comparing case-sensitively
"Admin" is not "admin". Store normalised values; role names are lowercase.
18. Over-clever rules
If you can’t explain a rule in a sentence, split it into named rules. Complex rules hide bugs.Testing
Catch these.
Debugging
Diagnose them.