Gotchas
The short list. Each item links to the page that explains it.
Numbers and arguments
Section titled “Numbers and arguments”u64,i64andVec<u8>travel as decimal strings and base64url, in arguments, results, record fields, errors and events. A client sends{"size": "7"}, not{"size": 7}.- The same types nested in another type (
Vec<u64>,Option<Vec<i64>>) do not compile: wrap them in aRecordor send strings (SDK macros). - A
u64inside your own plain serde struct is invisible to the macro and reaches JSON as a number, which JavaScript may round. Use aRecord, whose derive converts it. - Arguments are camelCase (
room_id→roomId), and unknown keys are refused (BadArgs).
- Renaming a state field or changing its type orphans its data: an upgrade keeps the state and has no migration step (Upgrades & state).
- A record must not also derive
Serialize/Deserialize:#[derive(Record)]writes them. - Uniqueness belongs in the key or a
unique(..)constraint, not in a check before an insert. - Prefer
env::unique_id()to aCounterfor ids. - Multi-row reads are pages of at most 1,000; follow
next(Tables & Collections).
Access
Section titled “Access”- A method with no attribute admits any signed-in account the node lets reach
the app; org membership is the app’s to check with
guards(Access control). - Take the caller from
env::caller()or a guard, never from an argument. #[app::error]and#[app::event]must be in the#[app::logic]module, or the ABI lists none of them.
- A call that fails writes nothing and emits nothing; a panic is a trap, not an app error (Error handling).
env::xcallonly queues a message: it is delivered after the entry commits, and only if the run succeeds (Cross-app calls).- Only views may search; a call that searches traps (Search).
env::fetch, actions and cross-app calls answer an error on the host target; test them withTestApp(Testing).- A read-only team member reaches an app’s views only: a call to any other
method is refused with
403before it runs.