> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sigmic.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Understanding error responses and error codes

# Error Handling

When an API request fails, you'll receive a structured error response with details about what went wrong.

## Error Response Format

All errors follow this consistent format:

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Human-readable error description",
    "code": "ERROR_CODE"
  }
}
```

| Field           | Description                                             |
| --------------- | ------------------------------------------------------- |
| `success`       | Always `false` for error responses                      |
| `error.message` | A human-readable description of the error               |
| `error.code`    | A machine-readable error code for programmatic handling |

## Error Codes

### Authentication Errors

| Code                  | HTTP Status | Description                                                      |
| --------------------- | ----------- | ---------------------------------------------------------------- |
| `AUTH_REQUIRED`       | 401         | No authentication was provided in the request headers            |
| `INVALID_API_KEY`     | 401         | The API key is invalid, malformed, or has expired                |
| `INVALID_AUTH_FORMAT` | 401         | Token format not recognized (must start with `sigmic_` or `eyJ`) |
| `INVALID_TOKEN`       | 401         | JWT is invalid or has expired                                    |
| `JWT_NOT_CONFIGURED`  | 501         | Server does not have JWT signing configured                      |
| `ORIGIN_NOT_ALLOWED`  | 403         | Request origin not in widget app's allowed origins list          |

**Example (API key):**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Authentication required",
    "code": "AUTH_REQUIRED"
  }
}
```

### Widget Token Errors

| Code                  | HTTP Status | Description                                               |
| --------------------- | ----------- | --------------------------------------------------------- |
| `MISSING_CREDENTIALS` | 400         | `appId` or `appSecret` not provided in token request      |
| `MISSING_END_USER_ID` | 400         | `endUserId` not provided or empty                         |
| `INVALID_CREDENTIALS` | 401         | Widget app credentials are invalid                        |
| `INVALID_EXPIRES_IN`  | 400         | `expiresIn` format invalid (must be e.g. `"1h"`, `"30m"`) |
| `INVALID_ENV`         | 400         | Invalid env var name or non-string value                  |

**Example (token exchange):**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Invalid app credentials",
    "code": "INVALID_CREDENTIALS"
  }
}
```

### Authorization Errors

| Code        | HTTP Status | Description                                      |
| ----------- | ----------- | ------------------------------------------------ |
| `FORBIDDEN` | 403         | You don't have permission to perform this action |

These errors occur when your authentication is valid but you lack the required role. Common scenarios:

* A **member** tries to perform an **admin**-only action (inviting members, changing roles)
* A user tries to access a project they haven't been granted access to
* A non-admin tries to manage project members

**Example:**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Admin access required."
  }
}
```

### Resource Errors

| Code        | HTTP Status | Description                                             |
| ----------- | ----------- | ------------------------------------------------------- |
| `NOT_FOUND` | 404         | The requested resource (task, tool call) does not exist |

**Example:**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Task not found",
    "code": "NOT_FOUND"
  }
}
```

### Validation Errors

| Code               | HTTP Status | Description                               |
| ------------------ | ----------- | ----------------------------------------- |
| `VALIDATION_ERROR` | 400         | Request parameters are invalid or missing |

**Examples:**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Message is required",
    "code": "VALIDATION_ERROR"
  }
}
```

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Invalid env var name: 123BAD",
    "code": "VALIDATION_ERROR"
  }
}
```

### Task Execution Errors

| Code              | HTTP Status | Description                                           |
| ----------------- | ----------- | ----------------------------------------------------- |
| `EXECUTION_ERROR` | 500         | Task execution failed due to an internal error        |
| `ALREADY_RUNNING` | 400         | Cannot perform action because task is already running |

**Example:**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Task is already running",
    "code": "ALREADY_RUNNING"
  }
}
```

## Handling Errors in Code

### JavaScript

```javascript theme={null}
async function makeRequest(url, options) {
  const response = await fetch(url, options);
  const data = await response.json();

  if (!data.success) {
    switch (data.error.code) {
      case 'AUTH_REQUIRED':
      case 'INVALID_API_KEY':
        throw new Error('Authentication failed: ' + data.error.message);

      case 'NOT_FOUND':
        throw new Error('Resource not found: ' + data.error.message);

      case 'VALIDATION_ERROR':
        throw new Error('Invalid request: ' + data.error.message);

      default:
        throw new Error('API error: ' + data.error.message);
    }
  }

  return data;
}
```

### Python

```python theme={null}
import requests

def make_request(url, **kwargs):
    response = requests.request(**kwargs, url=url)
    data = response.json()

    if not data.get('success'):
        error = data.get('error', {})
        code = error.get('code', 'UNKNOWN')
        message = error.get('message', 'Unknown error')

        if code in ['AUTH_REQUIRED', 'INVALID_API_KEY']:
            raise AuthenticationError(message)
        elif code == 'NOT_FOUND':
            raise NotFoundError(message)
        elif code == 'VALIDATION_ERROR':
            raise ValidationError(message)
        else:
            raise APIError(message)

    return data
```

## SSE Stream Errors

Errors during streaming are delivered as `error` events:

```
event: error
data: {"type":"error","data":{"message":"Task execution failed","code":"EXECUTION_ERROR"}}
```

Handle these within your SSE parsing logic:

```javascript theme={null}
if (eventType === 'error') {
  console.error(`Error: ${data.data.message} (${data.data.code})`);
  // Clean up and handle the error
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Always check success field" icon="check">
    Even on 200 responses, verify `success: true` before processing data
  </Card>

  <Card title="Log error codes" icon="file-lines">
    Log the `code` field for debugging and monitoring
  </Card>

  <Card title="Implement retries" icon="rotate">
    For transient errors (5xx), implement exponential backoff retries
  </Card>

  <Card title="Validate inputs" icon="shield">
    Validate inputs client-side to avoid unnecessary API calls
  </Card>
</CardGroup>
