Start with the symptom.

”My list is empty but there is data”

  1. Who is signed in? await pawabase.auth.getSession(). Signed out is a different caller from signed in.
  2. What does the list rule allow? Open the table’s Access tab. With the owner set, a person sees only rows whose owner column equals their id.
  3. Is the owner column filled? In the table editor, look at the row’s owner_id. An empty owner never matches owner.
  4. Try the same call with a secret key on a server. If it returns rows, an access rule is the cause.
  5. Is your filter right? Remove filters one at a time.

”get says not found, but I can see it in Studio”

Studio shows everything. get says “not found” when the record is missing or your rule hides it. Check the rule and the owner column as above. See Access.

”Create works but I can’t see what I created”

The owner column wasn’t set, so the list/get rule can’t match it. Either the table has no owner_field, or a server created it without a user. Set the owner explicitly.

”403 on a write”

A signed-in caller was refused by the rule for that action. In TypeScript error.policy names it. Find the request in Activity (use error.requestId) to see which rule and why. See Testing rules.

”401”

The rule needs a signed-in user and the request had none, or the token expired. Check the session and that you aren’t using a client created before sign-in with a stale token.

”Validation error”

The message names the column. Compare with the column’s rules: required, type, min_length, pattern, allowed values. error.byField() gives them all.

”Conflict (409)”

A unique column or unique index rejected a duplicate. Find the existing row, or use upsert in an import.

”The table doesn’t exist” or “column not found”

The definition has changes the table lacks. Open History for the pending migration and apply it, or run migrate. See Migrations and history. If someone changed the table with SQL, acknowledge it.

”A migration failed”

”A list is slow”

  1. Which filter and sort? Are those columns indexed?
  2. Run explain in the SQL editor: a sequential scan on a big table means no usable index.
  3. Are you expanding a big has_many? Load children separately.
  4. Are you fetching all columns? select(...) fewer.
  5. Is the rule checked per row? Prefer a plain equality rule, so it becomes a database filter.

”Pages are short or total is null”

A rule that can’t become a database filter is checked per row after the query. Pages can be short and total unknown. Stop on a short page, or change the rule.

”Live updates don’t arrive”

  • Broadcast changes must be on for the table.
  • The person’s read rule must allow the row.
  • You subscribed to resource:<table> with the exact name.
  • If the change was made with SQL, turn on Capture changes made outside the API. See Live records.

”429 Too many requests”

The table’s rate limit, your API access settings, or your plan. The client already retries; show retryAfter.

”An imported row didn’t run my flow”

Imports are quiet by default. Turn on Run events, flows and realtime for each row.

”Stale data after an SQL change”

Response caching. SQL from the editor clears caches; other writers don’t. Call m.cache.invalidate({ resources: ["products"] }).

Collect the right information

When asking for help, include: the call you made, the table’s definition (m.resources.getOne), who was signed in, the error’s status, code and requestId.

Errors

Every error type.

Access rules

Understand the rules.