# Throwing errors

> Using errors to control flow in Orbital

Source: https://orbitalhq.com/docs/querying/errors

## Overview

In Orbital and Taxi, error handling is managed through a `throw` function that allows users to 
control the response sent back to the user. 

This includes setting the error code and the response payload. Note that currently, we do not support catching errors; 
throwing an error is a fatal action. This will be addressed in a future release.

## Throwing Errors

Errors are thrown using the `throw` function. The syntax for throwing an error is:

```kotlin
throw((ErrorType) { errorPayload })
```

This is actually a casting operation, casting the payload value to the defined error type. This is
because Taxi does not have a concept of constructors, or object creation.

For example, given a `NotAuthorizedError`, defined as follows:

```taxi NotAuthorized.taxi
import com.orbitalhq.errors.Error

model NotAuthorizedError inherits Error {
  message: ErrorMessage
}
```

This would be thrown as follows:

```taxi
throw((NotAuthorizedError) { message: "Authentication failed" })
```

Here, `(NotAuthorizedError)` is a casting statement, as Taxi does not have the concept of constructors.

### Defining Errors

Errors are defined as models in Taxi. An error model must inherit from the base `Error` type (`com.orbitalhq.errors.Error`) and can include 
annotations to control the HTTP response code and the response body. Below are examples of how to define and use error models.

### Example: NotAuthorizedError

The `NotAuthorizedError` is provided out-of-the-box and is defined as follows:

```taxi
@ResponseCode(401)
model NotAuthorizedError inherits Error {
  message: ErrorMessage
}
```

To throw this error with a custom message:

```taxi
throw((NotAuthorizedError) { message: "Authentication failed" })
```

## Response Codes and Payloads

When an error is thrown, users can control the HTTP response code and the response payload using annotations.

### Example: Custom Response Code

If no response code is provided, the default response code is 400. To specify a custom response code, use the `@ResponseCode` annotation:

**Note: Don't forget the import**
Don't forget to include the import of `taxi.http.ResponseCode`


```taxi
import taxi.http.ResponseCode

@ResponseCode(403)
model NotAuthorizedError inherits Error {
  message: ErrorMessage
}
```

### Example: Custom Response Body

To customize the response body, use the `@ResponseBody` annotation:

**Note: Don't forget the import**
Don't forget to include the import of `taxi.http.ResponseBody`


```taxi
import taxi.http.ResponseBody

model BadPermissionsError inherits Error {
  @ResponseBody
  error: {
    errorCode: String
    message: String
  }
}
```

Thrown as follows:

```taxi
throw( (BadPermissionsError) 
  { error: 
    { errorCode: 'E1234', message: "You didn't say the magic word" }
  }
)
```

This would generate an error as follows:

```json
{
  "errorCode" : "E1234",
  "message" : "You didn't say the magic word"
}
```

## Built-in errors

As part of the release in 0.34, the following errors will be provided out-of-the-box.

| **Error Type**                  | **Description**                                                                         | **HTTP Response Code**     |
|---------------------------------|-----------------------------------------------------------------------------------------|----------------------------|
| **OperationFailedError**        | Thrown when an operation fails to be invoked (e.g., a server returned a 4xx/5xx error). | 400 (Client Error)         |
| **ModelContractViolationError** | Thrown when a model cannot be constructed, generally because data was missing.          | 422 (Unprocessable Entity) |
| **ParseError**                  | Thrown when source content could not be parsed (e.g., malformed JSON or CSV).           | 400 (Bad Request)          |
| **DataNotDiscoverableError**    | Thrown when the query asked for data, but no services could provide the requested data. | 404 (Not Found)            |
| **NotAuthorizedError**          | Thrown to indicate that a requested data attribute or service call has been rejected.   | 403 (Forbidden)            |
