mirror of
https://github.com/supabase/supabase.git
synced 2026-07-24 08:30:05 -04:00
3dffdefd6e
Closes DOCS-1057 Contributes to DOCS-1052 ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## Problem We have hundreds of MDX lint warnings in our docs going against style best practices. ## Solution Remove and replace in context the following: - PostgreSQL. There was only one. There was concern about exceptions, but I found none. - Just - Quickly - Actually ### What changed Edits follow the [Google developer documentation style guide](https://developers.google.com/style): concise, direct, active voice. The flagged words were removed when the sentence still read well, or replaced when meaning needed to be preserved. ### Common patterns | Flagged word | Approach | Example | |---|---|---| | **just** (filler) | Removed | "you just installed" → "you installed" | | **just** (limiting) | **only** | "just one row" → "only one row" | | **just like** | **like** / **the same as** | "function just like regular users" → "function like regular users" | | **not just** | **not only** | "not just errors" → "not only errors" | | **quickly** (performance) | **efficiently** or removed | "find rows quickly" → "find rows efficiently" | | **quickly** (time) | **soon** / **rapidly** / removed | "expires too quickly" → "expires too soon" | | **actually** (filler) | Removed | "actually execute" → "execute"; "is actually the most common" → "is the most common" | ## Tophatting 1. See the diff. 2. See that content continues to make sense in context. 3. Locally, `cd apps/docs` and run `pnpm run lint:mdx`. 4. Search for "just," "actually," "quickly", and "PostgreSQL" and see there are 0 warnings. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated wording across quickstarts, guides, and troubleshooting articles for grammar, clarity, and consistent step-by-step phrasing. * Clarified key concepts including Row Level Security policy evaluation across Supabase products, deferred foreign key constraint behavior, and when `EXPLAIN ANALYZE` executes queries (and related side effects). * Refined several troubleshooting instructions and added guidance to cap log payload size to reduce billed Logs Ingest volume. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Nik Richers <nrichers@gmail.com> Co-authored-by: Chris Chinchilla <chris.ward@supabase.io>
146 lines
5.3 KiB
Plaintext
146 lines
5.3 KiB
Plaintext
---
|
|
id: handling-errors-in-supabase-js
|
|
title: 'Handling errors in `supabase-js`'
|
|
subtitle: 'Read `error.hint` first — Postgres often tells you the exact fix. Log the full error so you actually see it.'
|
|
---
|
|
|
|
Every `supabase-js` call returns a `{ data, error }` pair instead of throwing. When something fails, the single most useful field on `error` is usually `hint` — Postgres returns the _fix_, not only a description of the problem. Logging only `error.message` hides it.
|
|
|
|
## Usage of `message` and `hint` properties
|
|
|
|
Consider a `42501` permission-denied error on a table where default `GRANT`s have been revoked from `anon`:
|
|
|
|
```
|
|
message: "permission denied for table users"
|
|
hint: "Grant the required privileges to the current role with: GRANT SELECT ON public.users TO anon;"
|
|
```
|
|
|
|
The `message` exposes the error reason, and `hint` gives you the literal SQL statement to run in the dashboard SQL editor to fix it.
|
|
|
|
The same pattern shows up across many Postgres errors — missing column? `hint` suggests the column name you probably meant. Type mismatch? `hint` shows the expected type. Whenever Postgres knows the fix, it puts it in `hint`.
|
|
|
|
<Admonition type="tip">Log the full `error` object, not only `error.message`.</Admonition>
|
|
|
|
## The recommended pattern
|
|
|
|
Read `{ data, error }` from the response, check `error`, log the whole object, and return early.
|
|
|
|
```ts
|
|
const { data, error } = await supabase.from('users').select()
|
|
if (error) {
|
|
console.error(error)
|
|
return
|
|
}
|
|
```
|
|
|
|
In the case of a permission-denied error, the response body will look like this:
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "42501",
|
|
"message": "permission denied for table users",
|
|
"details": null,
|
|
"hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.users TO anon;"
|
|
},
|
|
"status": 401,
|
|
"statusText": "Unauthorized"
|
|
}
|
|
```
|
|
|
|
`postgrest-js` passes the body through verbatim, so `error.hint` is the exact string Postgres produced. Treat it as the answer the database is giving you, not as a suggestion to file away.
|
|
|
|
## The `PostgrestError` fields, by usefulness
|
|
|
|
Database calls (`select`, `insert`, `update`, `upsert`, `delete`, `rpc`) return a `PostgrestError` with four fields. Read them in roughly this order:
|
|
|
|
| Field | Read it when |
|
|
| --------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
| `hint` | Always check first. When Postgres includes one, it's the actionable fix (a `GRANT` to run, a column name, a type). |
|
|
| `code` | When branching in code. Codes are stable across versions; `message` text isn't. |
|
|
| `details` | When `hint` and `message` aren't enough. Often contains the offending value, key, or row. |
|
|
| `message` | As the human summary. Useful in UI strings, less useful for debugging. |
|
|
|
|
A full list of PostgREST error codes is in the [Error Codes reference](/guides/api/rest/postgrest-error-codes).
|
|
|
|
## Branch on `error.code`, not `error.message`
|
|
|
|
`error.code` is more reliable than `error.message` for programmatic branching: messages change between Postgres and PostgREST versions, but codes are stable.
|
|
|
|
```ts
|
|
const { data, error } = await supabase.from('users').select()
|
|
if (error) {
|
|
console.error(error)
|
|
if (error.code === '42501') {
|
|
// Permission denied. error.hint usually contains the GRANT to run.
|
|
}
|
|
return
|
|
}
|
|
```
|
|
|
|
## Errors from Auth, Storage, and Edge Functions
|
|
|
|
The same rule applies across the SDK — log the whole error object — but the shape differs by client.
|
|
|
|
### Auth
|
|
|
|
`AuthError` exposes `error.code` (e.g. `'invalid_credentials'`, `'email_not_confirmed'`) and `error.status`. Branch on `code`; log the whole thing.
|
|
|
|
```ts
|
|
const { data, error } = await supabase.auth.signInWithPassword({
|
|
email: 'example@email.com',
|
|
password: 'example-password',
|
|
})
|
|
if (error) {
|
|
console.error(error)
|
|
return
|
|
}
|
|
```
|
|
|
|
### Storage
|
|
|
|
`StorageError` exposes `error.statusCode` (HTTP status as a string) and a structured `error` name (e.g. `'Duplicate'`, `'NotFound'`).
|
|
|
|
```ts
|
|
const { data, error } = await supabase.storage
|
|
.from('avatars')
|
|
.upload('public/avatar1.png', avatarFile)
|
|
if (error) {
|
|
console.error(error)
|
|
return
|
|
}
|
|
```
|
|
|
|
### Edge Functions
|
|
|
|
Functions errors arrive as one of three subclasses. Narrow with `instanceof`; for `FunctionsHttpError`, parse the body to get the function's own error payload.
|
|
|
|
```ts
|
|
import { FunctionsFetchError, FunctionsHttpError, FunctionsRelayError } from '@supabase/supabase-js'
|
|
|
|
const { data, error } = await supabase.functions.invoke('hello')
|
|
if (error instanceof FunctionsHttpError) {
|
|
console.error('Function error', await error.context.json())
|
|
} else if (error) {
|
|
console.error(error)
|
|
}
|
|
```
|
|
|
|
### Realtime
|
|
|
|
The `subscribe()` callback receives a `status` and, on failure, an `err` argument. Log the whole `err` — its `cause` often holds the underlying reason.
|
|
|
|
```ts
|
|
supabase.channel('room1').subscribe((status, err) => {
|
|
if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT') {
|
|
console.error(status, err)
|
|
}
|
|
})
|
|
```
|
|
|
|
## Related
|
|
|
|
- [PostgREST Error Codes](/guides/api/rest/postgrest-error-codes)
|
|
- [Automatic retries with `supabase-js`](/guides/api/automatic-retries-in-supabase-js)
|
|
- [Securing your API](/guides/api/securing-your-api)
|