Error Code Catalog
Complete reference for all ObjectStack error codes with causes, fixes, and retry strategies
Error Code Catalog
ObjectStack uses a structured error system with 9 error categories and 51 standardized error codes. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
Source: packages/spec/src/api/errors.zod.ts
Import: import { StandardErrorCode, ErrorCategory, ErrorResponseSchema } from '@objectstack/spec/api'
Spec vs. wire format: The codes below are StandardErrorCode — the standardized, lowercase snake_case contract that plugin/hook authors should throw with (see Server-Side Error Handling). The kernel REST server (@objectstack/rest) that serves /api/v1/data/* today emits a flatter envelope with SCREAMING_SNAKE_CASE codes instead — e.g. VALIDATION_FAILED, PERMISSION_DENIED, RECORD_NOT_FOUND, CONCURRENT_UPDATE — not the codes in this catalog. See the API Overview for both wire formats in use and Wire Format for JSON examples.
Error Categories
| Category | HTTP Status | Description |
|---|---|---|
validation | 400 | Request data failed validation |
authentication | 401 | Identity not verified |
authorization | 403 | Insufficient permissions |
not_found | 404 | Resource does not exist |
conflict | 409 | State conflict or duplicate |
rate_limit | 429 | Too many requests |
server | 500 | Internal server error |
external | 502 | External service failure |
maintenance | 503 | System under maintenance |
Retry Strategies
| Strategy | Description | When to Use |
|---|---|---|
no_retry | Do not retry the request | Validation errors, permission denied |
retry_immediate | Retry immediately | Transient network errors |
retry_backoff | Retry with exponential backoff | Rate limits, server errors |
retry_after | Wait the specified retryAfter seconds | Rate limit with explicit cooldown |
Validation Errors (400)
validation_error
Cause: Generic validation failure — request body does not match expected schema.
Fix: Check the fieldErrors array for specific field-level issues.
Retry: no_retry
{
"code": "validation_error",
"message": "Request validation failed",
"category": "validation",
"httpStatus": 400,
"retryable": false,
"fieldErrors": [
{ "field": "email", "message": "Invalid email format", "code": "invalid_format" }
]
}invalid_field
Cause: A field name in the request does not exist on the target object.
Fix: Check the object schema for valid field names. Use os meta get object <name> to inspect the object's fields.
Retry: no_retry
missing_required_field
Cause: A required field was not provided in the request body.
Fix: Include the missing field. Check fieldErrors for the field name.
Retry: no_retry
invalid_format
Cause: Field value does not match the expected format (e.g., invalid email, wrong date format).
Fix: Ensure the value matches the field's format constraint or built-in type validation.
Retry: no_retry
value_too_long
Cause: String value exceeds the field's maxLength constraint.
Fix: Truncate the value to the maximum allowed length.
Retry: no_retry
value_too_short
Cause: String value is below the field's minLength constraint.
Fix: Provide a longer value that meets the minimum length requirement.
Retry: no_retry
value_out_of_range
Cause: Numeric value is outside the field's min/max range.
Fix: Ensure the value is within the allowed range.
Retry: no_retry
invalid_reference
Cause: A lookup or master_detail field references a record that does not exist.
Fix: Verify the referenced record ID exists in the target object.
Retry: no_retry
duplicate_value
Cause: A field with unique: true already has a record with the same value.
Fix: Use a different value or update the existing record.
Retry: no_retry
invalid_query
Cause: The query structure is malformed.
Fix: Check the query syntax against the Query Cheat Sheet.
Retry: no_retry
invalid_filter
Cause: A filter operator or field in the where clause is invalid.
Fix: Use valid filter operators ($eq, $ne, $gt, $lt, $in, $contains, etc.).
Retry: no_retry
invalid_sort
Cause: The orderBy clause references a non-existent or non-sortable field.
Fix: Ensure the field exists and has sortable: true.
Retry: no_retry
max_records_exceeded
Cause: The request attempts to create or return more records than the system limit.
Fix: Use pagination (limit/offset or cursor-based) for large datasets. Batch operations for bulk creates.
Retry: no_retry
Authentication Errors (401)
unauthenticated
Cause: No authentication credentials were provided.
Fix: Include a valid Authorization header (Bearer token, API key, or session cookie).
Retry: no_retry
invalid_credentials
Cause: Username/password combination is incorrect.
Fix: Verify credentials and try again. After multiple failures, account may be locked.
Retry: no_retry
expired_token
Cause: The authentication token (JWT, session token) has expired.
Fix: Obtain a new token using the refresh token endpoint or re-authenticate.
Retry: retry_immediate (after refreshing token)
invalid_token
Cause: The authentication token is malformed or has been tampered with.
Fix: Obtain a fresh token from the authentication endpoint.
Retry: no_retry
session_expired
Cause: The user session has timed out due to inactivity.
Fix: Re-authenticate to start a new session.
Retry: no_retry
mfa_required
Cause: Multi-factor authentication is required but the MFA challenge has not been completed.
Fix: Complete the MFA verification step before proceeding.
Retry: no_retry
email_not_verified
Cause: The user's email address has not been verified.
Fix: Complete email verification through the link sent to the user's email.
Retry: no_retry
Authorization Errors (403)
permission_denied
Cause: The authenticated user does not have permission for this operation.
Fix: Request the necessary permissions from an administrator, or use an account with the required role.
Retry: no_retry
insufficient_privileges
Cause: The user has some access but lacks the specific privilege required for this action.
Fix: Contact an administrator to grant the necessary privilege.
Retry: no_retry
field_not_accessible
Cause: The user does not have access to a specific field on the object.
Fix: Remove the inaccessible field from the request, or request field-level access.
Retry: no_retry
record_not_accessible
Cause: The user cannot access this specific record due to record-level sharing rules.
Fix: Request access to the record from its owner or an administrator.
Retry: no_retry
license_required
Cause: The feature requires a specific license that is not active.
Fix: Upgrade the license or contact your administrator.
Retry: no_retry
ip_restricted
Cause: The request originates from an IP address that is not in the allowlist.
Fix: Ensure the request comes from an approved IP range, or update the IP restriction settings.
Retry: no_retry
time_restricted
Cause: Access is limited to specific time windows and the current time is outside the allowed range.
Fix: Retry during the allowed time window.
Retry: retry_after
Not Found Errors (404)
resource_not_found
Cause: The requested resource does not exist (generic).
Fix: Verify the resource identifier and endpoint path.
Retry: no_retry
object_not_found
Cause: The specified object (table/entity) does not exist in the schema.
Fix: Check the object name. Use os meta list object to list available objects.
Retry: no_retry
record_not_found
Cause: No record exists with the given ID in the specified object.
Fix: Verify the record ID. The record may have been deleted.
Retry: no_retry
field_not_found
Cause: The specified field does not exist on the object.
Fix: Check the field name against the object schema. Field names are snake_case.
Retry: no_retry
endpoint_not_found
Cause: The API endpoint path does not match any registered route.
Fix: Verify the URL path and HTTP method. Check the API discovery endpoint for available routes.
Retry: no_retry
Conflict Errors (409)
resource_conflict
Cause: The operation conflicts with the current state of the resource.
Fix: Fetch the latest resource state and retry the operation.
Retry: retry_immediate
concurrent_modification
Cause: The record was modified by another user/process since you last read it (optimistic locking failure).
Fix: Re-fetch the record, merge changes, and retry.
Retry: retry_immediate
delete_restricted
Cause: The record cannot be deleted because other records depend on it (referential integrity).
Fix: Delete or reassign dependent records first, then retry the delete.
Retry: no_retry
duplicate_record
Cause: A record with the same unique key already exists.
Fix: Update the existing record instead, or use a different unique key value.
Retry: no_retry
lock_conflict
Cause: The record is locked by another process or user.
Fix: Wait for the lock to be released, or contact the lock holder.
Retry: retry_backoff
Rate Limit Errors (429)
rate_limit_exceeded
Cause: Too many requests in the current time window.
Fix: Reduce request frequency. Check the retryAfter field for the wait time.
Retry: retry_after
quota_exceeded
Cause: The API usage quota for the current period has been exhausted.
Fix: Wait for the quota to reset (check retryAfter), or upgrade the plan.
Retry: retry_after
concurrent_limit_exceeded
Cause: Too many concurrent requests from the same client.
Fix: Reduce parallel request count. Implement request queuing.
Retry: retry_backoff
Server Errors (500)
internal_error
Cause: An unexpected server-side error occurred.
Fix: Report the issue with the requestId and traceId. Retry may succeed.
Retry: retry_backoff
database_error
Cause: A database operation failed (connection, query, constraint).
Fix: Report the issue. May be transient — retry with backoff.
Retry: retry_backoff
timeout
Cause: The operation exceeded the maximum allowed time.
Fix: Simplify the query/operation. For large datasets, use pagination or async processing.
Retry: retry_backoff
service_unavailable
Cause: A required internal service is temporarily unavailable.
Fix: Retry after a brief delay. Check system status.
Retry: retry_backoff
not_implemented
Cause: The requested feature or endpoint is not yet implemented.
Fix: Check the documentation for alternative approaches, or wait for the feature release.
Retry: no_retry
External Service Errors (502)
external_service_error
Cause: An external API or service returned an error.
Fix: Check the external service status. The details field may contain the upstream error.
Retry: retry_backoff
integration_error
Cause: An integration connector encountered an error.
Fix: Verify the integration configuration and credentials.
Retry: retry_backoff
webhook_delivery_failed
Cause: A webhook delivery attempt failed (target unreachable or returned error).
Fix: Verify the webhook URL is accessible. The system will auto-retry per delivery policy.
Retry: retry_backoff
Batch Operation Errors
batch_partial_failure
Cause: Some operations in a batch request succeeded while others failed.
Fix: Check the details for individual operation results. Retry only the failed operations.
Retry: retry_immediate (failed operations only)
batch_complete_failure
Cause: All operations in the batch request failed.
Fix: Check the details for root cause. Fix and retry the entire batch.
Retry: retry_backoff
transaction_failed
Cause: A database transaction failed and was rolled back.
Fix: Check the details for the specific failure. Retry the entire transaction.
Retry: retry_backoff
Error Response Structure
Every error response follows the EnhancedApiError schema:
interface EnhancedApiError {
code: StandardErrorCode; // Machine-readable error code
message: string; // Human-readable description
category?: ErrorCategory; // Error category
httpStatus?: number; // HTTP status code
retryable: boolean; // Whether retry may succeed
retryStrategy?: RetryStrategy; // Recommended retry approach
retryAfter?: number; // Seconds to wait (for rate limits)
details?: unknown; // Additional error context
fieldErrors?: FieldError[]; // Field-specific validation errors
timestamp?: string; // ISO 8601 timestamp
requestId?: string; // Request tracking ID
traceId?: string; // Distributed trace ID
documentation?: string; // URL to error documentation
helpText?: string; // Suggested resolution actions
}Field Error Structure
interface FieldError {
field: string; // Field path (supports dot notation)
code: StandardErrorCode; // Field-level error code
message: string; // Human-readable error for this field
value?: unknown; // The invalid value (if safe to include)
constraint?: unknown; // The constraint that was violated (e.g., max length)
}Client-Side Error Handling
The @objectstack/client SDK's built-in fetch error handling attaches only
code, category, httpStatus, retryable, and details to the thrown
error — not fieldErrors, retryAfter, or requestId directly. If your
server populates those on the response body, read them from
apiError.details (e.g. apiError.details?.fieldErrors) until the client
surfaces them at the top level.
TypeScript Example
import type { EnhancedApiError } from '@objectstack/spec/api';
async function handleApiCall() {
try {
const result = await client.data.create('task', { title: 'New Task' });
return result;
} catch (error) {
const apiError = error as EnhancedApiError;
switch (apiError.category) {
case 'validation':
// Show field-level errors to the user
apiError.fieldErrors?.forEach(fe => {
showFieldError(fe.field, fe.message);
});
break;
case 'authentication':
// Redirect to login
if (apiError.code === 'expired_token') {
await refreshToken();
return handleApiCall(); // Retry
}
redirectToLogin();
break;
case 'rate_limit':
// Wait and retry
const waitTime = apiError.retryAfter ?? 60;
await sleep(waitTime * 1000);
return handleApiCall();
case 'server':
case 'external':
// Log and retry with backoff
console.error(`Server error [${apiError.requestId}]:`, apiError.message);
break;
default:
showGenericError(apiError.message);
}
}
}HTTP Status Quick Reference
| Status | Category | Common Codes |
|---|---|---|
| 400 | validation | validation_error, invalid_field, missing_required_field, invalid_query |
| 401 | authentication | unauthenticated, expired_token, invalid_credentials |
| 403 | authorization | permission_denied, field_not_accessible, license_required |
| 404 | not_found | record_not_found, object_not_found, endpoint_not_found |
| 409 | conflict | concurrent_modification, duplicate_record, delete_restricted |
| 429 | rate_limit | rate_limit_exceeded, quota_exceeded |
| 500 | server | internal_error, database_error, timeout |
| 502 | external | external_service_error, integration_error |
| 503 | maintenance | service_unavailable |