> This page is for version v8.3.0 (default).
> For other versions, use one of these documentation indexes:
> - v8.3.0 (default): https://docs.workflows.com/v-8-3-0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.workflows.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.workflows.com/_mcp/server.

# Error Handling

![Mind Reasoner API](/_fern-img/466e07efd0202b28f29ec8dda3be88918c85104c2652efceb8ff717127f861ca.webp)

> **Predictable Errors**
>
> Mind Reasoner API uses standard
>
> HTTP status codes
>
> and returns consistent
>
> JSON
>
> error responses. Every error includes actionable information to help you resolve issues quickly.

## Error Response Format

All errors follow a consistent structure:

```json
{
  "error": "Error Type",
  "message": "Human-readable description of what went wrong",
  "code": "MACHINE_READABLE_CODE",
  "details": {
    "field": "parameter_name",
    "value": "invalid_value"
  }
}
```

---

## HTTP Status Codes

4️⃣

### Client Errors (4xx)

Your request has an issue. Check authentication, parameters, or permissions.

5️⃣

### Server Errors (5xx)

Something went wrong on our end. Retry with exponential backoff.

2️⃣

### Success (2xx)

Request succeeded. 200 (OK) or 201 (Created) indicate successful operations.

---

## Common Errors

#### Authentication

### 401 Unauthorized

**Cause:** Missing or invalid API key

**Response:**

```json
{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "code": "AUTH_FAILED"
}
```

**Solutions:**

1. Verify API key is correct
2. Check Authorization header format: `Bearer YOUR_KEY`
3. Ensure there's a space between "Bearer" and your key
4. Confirm key hasn't been revoked

**Example Fix:**

```javascript
// Wrong
headers: { 'Authorization': 'BearerYOUR_KEY' }

// Correct
headers: { 'Authorization': 'Bearer YOUR_KEY' }
```

---

### 403 Forbidden

**Cause:** Valid key but insufficient permissions

**Response:**

```json
{
  "error": "Forbidden",
  "message": "Your account doesn't have access to this resource",
  "code": "INSUFFICIENT_PERMISSIONS"
}
```

**Solutions:**

1. Check your subscription level
2. Verify resource belongs to your account
3. Ensure you have the required role
4. Contact support if issue persists

#### Validation

### 400 Bad Request

**Cause:** Invalid request parameters

**Response:**

```json
{
  "error": "Bad Request",
  "message": "Invalid file format. Supported formats: .vtt, .pdf, .docx",
  "code": "VALIDATION_ERROR",
  "details": {
    "field": "contentType",
    "provided": "text/plain",
    "expected": ["text/vtt", "application/pdf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
  }
}
```

**Common Causes:**

* Missing required parameters
* Invalid parameter types
* Unsupported file formats
* Malformed JSON

**Solutions:**

1. Review the `details` field for specific issues
2. Verify all required parameters are included
3. Check parameter types match API specification
4. Validate JSON syntax

**Example Fix:**

```javascript
// Wrong: Missing required parameter
{
  "mindId": "abc-123"
  // Missing: digitalTwinId and artifactId
}

// Correct: All required parameters
{
  "mindId": "abc-123",
  "digitalTwinId": "xyz-789",
  "artifactId": "def-456"
}
```

#### Not Found

### 404 Not Found

**Cause:** Resource doesn't exist

**Response:**

```json
{
  "error": "Not Found",
  "message": "Mind with ID 'abc-123' does not exist",
  "code": "RESOURCE_NOT_FOUND",
  "details": {
    "resourceType": "mind",
    "resourceId": "abc-123"
  }
}
```

**Solutions:**

1. Verify the ID is correct (copy-paste to avoid typos)
2. Check the resource hasn't been deleted
3. Ensure the resource belongs to your account
4. IDs are case-sensitive—match exactly

**Example Fix:**

```javascript
// Save IDs immediately after creation
const response = await createMind({ name: "Sarah" });
const mindId = response.mind.id;        // Save this!
const twinId = response.digitalTwin.id; // And this!

// Use saved IDs in subsequent requests
const snapshot = await createSnapshot({
  mindId: mindId,
  digitalTwinId: twinId,
  artifactId: artifactId
});
```

#### Rate Limiting

### 429 Too Many Requests

**Cause:** Exceeded rate limits

**Response:**

```json
{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Retry after 60 seconds",
  "code": "RATE_LIMIT_EXCEEDED",
  "retryAfter": 60
}
```

**Rate Limits:**

* **Default:** 100 requests per minute
* **Burst:** 20 requests per second
* **Daily:** 10,000 requests per day

**Solutions:**

1. Implement

   exponential backoff
2. Respect the `retryAfter` field
3. Cache responses

   when possible
4. Batch operations where applicable
5. Contact support for higher limits

**Example Implementation:**

```javascript
async function makeRequestWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.response?.status === 429) {
        const retryAfter = error.response.data.retryAfter || Math.pow(2, i);
        console.log(`Rate limited. Retrying after ${retryAfter}s...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
```

#### Server Errors

### 500 Internal Server Error

**Cause:** Unexpected server error

**Response:**

```json
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred. Please try again",
  "code": "INTERNAL_ERROR",
  "requestId": "req_abc123def456"
}
```

**Solutions:**

1. Retry the request (may be temporary)
2. Check status page for incidents
3. Contact support with `requestId` if persistent

---

### 503 Service Unavailable

**Cause:** Service temporarily unavailable (maintenance or high load)

**Response:**

```json
{
  "error": "Service Unavailable",
  "message": "Service temporarily unavailable. Please retry",
  "code": "SERVICE_UNAVAILABLE",
  "retryAfter": 30
}
```

**Solutions:**

1. Retry after the specified time
2. Implement exponential backoff
3. Check status page for scheduled maintenance

**Example Implementation:**

```javascript
async function makeRequestWithBackoff(fn, maxRetries = 5) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if ([500, 502, 503, 504].includes(error.response?.status)) {
        const backoffTime = Math.min(Math.pow(2, i) * 1000, 32000);
        console.log(`Server error. Retrying in ${backoffTime}ms...`);
        await new Promise(resolve => setTimeout(resolve, backoffTime));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
```

---

## Error Handling Patterns

### Basic Try-Catch

**`Node.js`**

```javascript title="Node.js"
try {
  const response = await axios.post(url, data, { headers });
  return response.data;
} catch (error) {
  if (error.response) {
    // API returned an error response
    console.error('API Error:', error.response.data);
    console.error('Status:', error.response.status);
  } else if (error.request) {
    // Request made but no response received
    console.error('Network Error:', error.message);
  } else {
    // Error setting up the request
    console.error('Error:', error.message);
  }
  throw error;
}
```

**`Python`**

```python title="Python"
import requests

try:
    response = requests.post(url, json=data, headers=headers)
    response.raise_for_status()
    return response.json()
except requests.exceptions.HTTPError as e:
    # API returned an error response
    print(f"API Error: {e.response.status_code}")
    print(f"Message: {e.response.json()}")
    raise
except requests.exceptions.ConnectionError as e:
    # Network error
    print(f"Network Error: {e}")
    raise
except requests.exceptions.RequestException as e:
    # Other request errors
    print(f"Request Error: {e}")
    raise
```

### Retry with Exponential Backoff

**`Node.js`**

```javascript title="Node.js"
async function makeRequestWithRetry(fn, options = {}) {
  const {
    maxRetries = 3,
    initialDelay = 1000,
    maxDelay = 32000,
    retryableStatuses = [408, 429, 500, 502, 503, 504]
  } = options;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const status = error.response?.status;
      const isRetryable = retryableStatuses.includes(status);
      const isLastAttempt = attempt === maxRetries - 1;

      if (!isRetryable || isLastAttempt) {
        throw error;
      }

      const delay = Math.min(
        initialDelay * Math.pow(2, attempt),
        maxDelay
      );

      console.log(`Retry attempt ${attempt + 1}/${maxRetries} after ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
const result = await makeRequestWithRetry(async () => {
  return await axios.post(url, data, { headers });
});
```

**`Python`**

```python title="Python"
import time
import requests

def make_request_with_retry(fn, max_retries=3, initial_delay=1, max_delay=32):
    retryable_statuses = [408, 429, 500, 502, 503, 504]

    for attempt in range(max_retries):
        try:
            return fn()
        except requests.exceptions.HTTPError as e:
            status = e.response.status_code
            is_retryable = status in retryable_statuses
            is_last_attempt = attempt == max_retries - 1

            if not is_retryable or is_last_attempt:
                raise

            delay = min(initial_delay * (2 ** attempt), max_delay)
            print(f"Retry attempt {attempt + 1}/{max_retries} after {delay}s")
            time.sleep(delay)

# Usage
result = make_request_with_retry(lambda: requests.post(
    url, json=data, headers=headers
).json())
```

---

## Best Practices

🔄

### Always Retry

* Implement exponential backoff for 5xx errors
* Respect `retryAfter` headers
* Set reasonable retry limits (3-5 attempts)
* Log retry attempts for debugging

📝

### Log Everything

* Log error responses with status codes
* Include `requestId` for support tickets
* Track error patterns over time
* Monitor rate limit usage

👤

### User-Friendly Messages

* Don't expose API errors directly to users
* Provide actionable error messages
* Offer alternative actions when possible
* Include support contact for persistent issues

---

## Debugging Checklist

When encountering errors, work through this checklist:

#### Check Status Code

Identify whether it's a client error (4xx) or server error (5xx). Client errors require changes to your request; server errors may be temporary.

#### Read Error Message

The `message` field provides human-readable context. The `details` field often contains specific parameter issues.

#### Review Documentation

Compare your request against the [API Reference](/api-reference) to ensure all required parameters are included and formatted correctly.

---

## Getting Help

> **Support Resources**
>
> If you're stuck:
>
> 1. **Check the docs:** Search this documentation for your specific error code
> 2. **Review examples:** Compare your code against working examples in [Getting Started](/api-getting-started)
> 3. **Contact support:** Email [support@reasoner.com](mailto:support@reasoner.com) with:
>    * Error message and status code
>    * Request ID (if provided)
>    * Code snippet (remove API keys!)
>    * What you've tried so far

---

## What's Next?

🚀

### Start Building

Ready to implement error handling? Follow the [Quick Start](/api-quick-start) guide with confidence.

📚

### API Reference

See all possible responses for each endpoint in the [API Reference](/api-reference) documentation.

🔐

### Authentication

Review authentication best practices in the [Authentication](/api-authentication) guide.