API
Errors
Every error code the API returns, with its HTTP status, message and what to do.
Every error has the same shape. Check error.code in your code; the message is for people and may change.
{
"error": { "code": "record_changed", "message": "The record changed. Reload it before saving." },
"meta": { "request_id": "3L3NP3J4G546CPCD6HAIMKRCM6", "response_time": 1 }
} Internal details never appear in an error. Send the request_id with a bug report so it can be found in the server log.
Request errors
| Status | Code | Message | What to do |
|---|---|---|---|
| 400 | invalid_input | Check the submitted values. | Fix the body, the query or a value type. Required fields must be present. |
| 400 | workspace_required | Send the workspace in the X-Workspace-ID header or use a workspace path. | Use a path with :workspace or send X-Workspace-ID. |
| 404 | not_found | The requested resource is unavailable. | Check the IDs. You also get this for things you may not see. |
Sign-in and permission errors
| Status | Code | Message | What to do |
|---|---|---|---|
| 401 | authentication_required | Authentication is required or credentials are invalid. | Send one valid token. Sign in again if it expired. |
| 403 | access_denied | You do not have permission to perform this action. | Ask the owner for a role with this access. |
| 403 | incorrect_password | The current password is incorrect. | Check the current password when changing it. |
| 429 | rate_limited | Too many requests. Try again later. | Wait for the Retry-After seconds, then retry. |
Conflict errors
| Status | Code | Message | What to do |
|---|---|---|---|
| 409 | already_exists | A conflicting resource or value already exists. | A unique value is taken. Use another value. |
| 409 | ambiguous_lookup | The lookup key matches more than one record. | Make the lookup field unique. |
| 409 | schema_changed | The schema changed. Reload it before retrying. | Read the collection again, then retry. |
| 409 | schema_dependency | Remove dependent indexes or lookups before changing field storage. | Remove the index or lookup first. |
| 409 | schema_requires_empty_collection | This schema change requires an empty collection. | Empty the collection or create a new field instead. |
| 409 | index_requires_unique_values | Resolve duplicate values before creating a unique index. | Remove duplicates, then add the index. |
| 409 | workspace_not_empty | The workspace still contains data. Confirm to delete everything. | Confirm the delete, or empty the workspace first. |
| 412 | record_changed | The record changed. Reload it before saving. | Read the record for a new ETag, then retry. |
| 412 | metadata_changed | The appearance changed. Reload it before saving. | Reload the collection settings, then save again. |
Server errors
| Status | Code | Message | What to do |
|---|---|---|---|
| 500 | internal_error | The request could not be completed. | Retry once. If it repeats, report it with the request_id. |
| 503 | setup_required | Complete installation setup before using this service. | Claim the installation in Studio first. |
| 503 | core_not_initialized | The service is not ready. | Wait a moment after startup and retry. |
| 503 | operation_unavailable | This operation is currently unavailable. | The feature is off or not supported on this database. |
Handle errors in code
const res = await fetch(url, options);
if (!res.ok) {
const { error, meta } = await res.json();
if (error.code === 'record_changed') {
// read the record again and retry
}
throw new Error(`${error.code}: ${error.message} (request ${meta.request_id})`);
} if res.StatusCode >= 400 {
var out struct {
Error struct{ Code, Message string } `json:"error"`
Meta struct {
RequestID string `json:"request_id"`
} `json:"meta"`
}
json.NewDecoder(res.Body).Decode(&out)
return fmt.Errorf("%s: %s (request %s)", out.Error.Code, out.Error.Message, out.Meta.RequestID)
} if not res.ok:
body = res.json()
error, meta = body["error"], body["meta"]
raise RuntimeError(f"{error['code']}: {error['message']} (request {meta['request_id']})")