Error reference
When a Mango REST API request fails, the server returns an HTTP error status code along with a JSON response body that describes the problem. This page documents the error response format, all standard HTTP status codes used by Mango, Mango-specific error codes, and how to handle errors programmatically.
Overview
Mango follows HTTP conventions for status codes: 2xx codes indicate success, 4xx codes indicate a client error, and 5xx codes indicate a server error. In addition to the standard HTTP status code, every error response includes a structured JSON body with Mango-specific details that help you diagnose the problem without guessing.
Error response format
All error responses from the Mango REST API share a consistent JSON structure:
{
"mangoStatusCode": 4000,
"mangoStatusName": "VALIDATION_FAILED",
"message": "Validation failed for object of type DataSourceVO",
"localizedMessage": "Validation failed for object of type DataSourceVO"
}
| Field | Type | Description |
|---|---|---|
mangoStatusCode | Integer | A Mango-specific numeric error code. More granular than the HTTP status code. |
mangoStatusName | String | A human-readable constant name for the error code (e.g., NOT_FOUND, ACCESS_DENIED). |
message | String | A description of the error in English. Includes specific details about what went wrong. |
localizedMessage | String | The error message localized to the user's configured language, if a translation is available. Falls back to English. |
Some error responses include additional fields depending on the error type. Validation errors, for example, include a result object with field-level error details (see the validation errors section below).
HTTP status codes
Mango uses the following standard HTTP status codes:
| Status code | Name | When returned |
|---|---|---|
200 | OK | Request succeeded. Response body contains the requested resource or result. |
201 | Created | A new resource was successfully created. Response body contains the created resource. The Location header contains the URL of the new resource. |
400 | Bad Request | The request body is malformed, missing required fields, or contains invalid values. Check the message field for details. |
401 | Unauthorized | No authentication credentials were provided, or the provided credentials are invalid or expired. |
403 | Forbidden | The authenticated user does not have permission to perform this operation. The user is authenticated but lacks the required role or data source access. |
404 | Not Found | The requested resource does not exist. Verify the resource ID or XID in the URL. |
409 | Conflict | The request conflicts with the current state of the server. Typically returned when attempting to create a resource with an XID that already exists. |
422 | Unprocessable Entity | The request body is syntactically valid JSON but fails business-logic validation. The response includes field-level validation errors. |
429 | Too Many Requests | The client has exceeded the rate limit. The response includes a Retry-After header indicating how many seconds to wait before retrying. |
500 | Internal Server Error | An unexpected error occurred on the server. This indicates a bug or infrastructure problem. Check the Mango server logs for a stack trace. |
Mango status codes
The mangoStatusCode provides more specific information than the HTTP status code alone. The following table lists the most common Mango status codes you will encounter:
| Mango status code | Status name | HTTP status | Description |
|---|---|---|---|
4000 | VALIDATION_FAILED | 422 | One or more fields failed validation. The response includes a result object with field-level error messages. |
4001 | NOT_FOUND | 404 | The requested resource was not found. The message field includes the resource type and identifier. |
4003 | ACCESS_DENIED | 403 | The authenticated user does not have the required permissions. This may be a missing role or insufficient data source access rights. |
4005 | ALREADY_EXISTS | 409 | A resource with the same unique identifier (XID or other unique constraint) already exists. Use a PUT/PATCH request to update the existing resource instead. |
4009 | INVALID_REQUEST | 400 | The request is structurally invalid -- malformed JSON, missing required headers, or unsupported content type. |
5000 | INTERNAL_SERVER_ERROR | 500 | An unexpected server-side error. The server logs contain the full stack trace. Report this to your Mango administrator. |
Validation errors
When a request fails validation (HTTP 422, mangoStatusCode 4000), the response includes a result object with detailed field-level error information:
{
"mangoStatusCode": 4000,
"mangoStatusName": "VALIDATION_FAILED",
"message": "Validation failed",
"localizedMessage": "Validation failed",
"result": {
"messages": [
{
"property": "name",
"level": "error",
"message": "is required",
"localizedMessage": "is required"
},
{
"property": "updatePeriods",
"level": "error",
"message": "must be greater than 0",
"localizedMessage": "must be greater than 0"
},
{
"property": "pointLocator.offset",
"level": "error",
"message": "must be between 0 and 65535",
"localizedMessage": "must be between 0 and 65535"
}
]
}
}
Validation message fields
| Field | Type | Description |
|---|---|---|
property | String | The JSON path to the field that failed validation. Nested fields use dot notation (e.g., pointLocator.offset). |
level | String | The severity: error (request rejected), warning (request accepted but may cause issues), or info (informational). |
message | String | Description of the validation failure in English. |
localizedMessage | String | Localized version of the message. |
Handling validation errors
When you receive a validation error, iterate over result.messages to identify which fields need correction. The property path corresponds directly to the field path in your request JSON.
Rate limiting
Mango enforces rate limits on API requests to protect server resources. When you exceed the limit, the server returns a 429 Too Many Requests response.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{
"mangoStatusCode": 4009,
"mangoStatusName": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"localizedMessage": "Rate limit exceeded. Try again in 30 seconds."
}
The Retry-After header contains the number of seconds to wait before sending another request. Always respect this header in your client code to avoid being blocked for longer periods.
Best practices to avoid rate limiting:
- Batch multiple operations into a single request where the API supports it (e.g., bulk data point value updates).
- Use WebSocket subscriptions for real-time point values instead of polling the REST API repeatedly.
- Cache responses client-side when the data does not change frequently.
- Implement exponential backoff in your retry logic.
Authentication errors
Authentication failures return a 401 Unauthorized response:
{
"mangoStatusCode": 4003,
"mangoStatusName": "ACCESS_DENIED",
"message": "Authentication required",
"localizedMessage": "Authentication required"
}
Common causes:
| Cause | Symptom | Resolution |
|---|---|---|
| No credentials provided | 401 on every request | Include an Authorization header or session cookie |
| Token expired | 401 after a period of successful requests | Refresh the authentication token or re-authenticate |
| Invalid password | 401 on login attempt | Verify the username and password |
| Account disabled | 401 with message "User is disabled" | Contact a Mango administrator to re-enable the account |
Code examples
JavaScript (fetch API)
async function getDataSource(xid) {
const response = await fetch(`/rest/latest/data-sources/by-xid/${xid}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
},
});
if (!response.ok) {
const error = await response.json();
if (error.mangoStatusCode === 4001) {
console.error(`Data source '${xid}' not found`);
return null;
}
if (error.mangoStatusCode === 4000 && error.result) {
// Validation errors -- log each field
for (const msg of error.result.messages) {
console.error(`Validation error on '${msg.property}': ${msg.message}`);
}
return null;
}
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 30;
console.warn(`Rate limited. Retrying in ${retryAfter} seconds.`);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
return getDataSource(xid); // retry
}
// Unexpected error
throw new Error(`API error ${error.mangoStatusCode}: ${error.message}`);
}
return response.json();
}
Python (requests library)
import requests
import time
MANGO_URL = "https://mango-host"
session = requests.Session()
session.auth = ("admin", "admin")
def get_data_source(xid):
response = session.get(f"{MANGO_URL}/rest/latest/data-sources/by-xid/{xid}")
if response.status_code == 200:
return response.json()
error = response.json()
if error.get("mangoStatusCode") == 4001:
print(f"Data source '{xid}' not found")
return None
if error.get("mangoStatusCode") == 4000:
result = error.get("result", {})
for msg in result.get("messages", []):
print(f"Validation error on '{msg['property']}': {msg['message']}")
return None
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 30))
print(f"Rate limited. Retrying in {retry_after} seconds.")
time.sleep(retry_after)
return get_data_source(xid) # retry
raise Exception(f"API error {error['mangoStatusCode']}: {error['message']}")
Common error scenarios
The following table maps frequently encountered errors to their root causes and resolutions:
| Error message | Status | Cause | Resolution |
|---|---|---|---|
| "is required" on a field | 422 | A required field was omitted from the request body | Add the missing field. Check the API documentation for required fields. |
| "Data source not found" | 404 | The XID or ID in the URL does not match any existing data source | Verify the XID. Use GET /rest/latest/data-sources to list available sources. |
| "Access denied" | 403 | The user lacks permission for this data source or operation | Grant the user the required role or data source read/write permission. |
| "XID is already in use" | 409 | A POST (create) request used an XID that belongs to an existing object | Use PUT to update the existing object, or choose a different XID. |
"must be greater than 0" on updatePeriods | 422 | The polling interval was set to zero or a negative number | Set updatePeriods to at least 1. |
| "Invalid JSON" or "Unexpected token" | 400 | The request body is not valid JSON | Validate your JSON with a linter. Check for missing commas, unclosed braces, or trailing commas. |
| "Authentication required" | 401 | No session cookie or Authorization header was sent | Authenticate first with POST /rest/latest/login or include a Bearer token. |
| "Internal server error" | 500 | An unexpected exception occurred in the server | Check the Mango server logs at mango-data/logs/ma.log for the full stack trace. Report the error to Radix IoT support if it persists. |
Related pages
- REST API overview -- Introduction to the Mango REST API
- Authentication -- How to authenticate and manage sessions
- RQL queries -- Filtering and querying resources
- API examples -- Practical examples for common API operations