# Error states

### Error Surfaces

There are two distinct error surfaces:

1. **Session or transport failures** These are returned before any tool execution begins.
2. **Tool-call failures** These are returned after a tool invocation starts.

### Session Or Transport Failures

#### Response format

When a session or transport failure returns a structured HTTP error, the response is:

```http
Content-Type: application/problem+json
```

with this body shape:

```json
{
  "type": "about:blank",
  "title": "<http status text, lowercased>",
  "instance": "<request URL>",
  "detail": "<error detail>"
}
```

Some transport failures return only an HTTP status code and an empty body. Those cases are called out explicitly below.

#### Guaranteed session and transport errors

| HTTP status | Body         | Detail                                    | When it is returned                                              |
| ----------- | ------------ | ----------------------------------------- | ---------------------------------------------------------------- |
| `401`       | problem JSON | `dev-id or x-api-key headers are missing` | Client credentials are missing.                                  |
| `401`       | problem JSON | `unauthorized`                            | Client credentials are invalid.                                  |
| `404`       | problem JSON | `missing user_id parameter`               | The required user identifier is missing.                         |
| `404`       | problem JSON | `invalid user id`                         | The supplied user identifier is malformed or not authorised.     |
| `500`       | problem JSON | `something went wrong`                    | A server-side failure occurs before MCP execution starts.        |
| `500`       | empty body   | none                                      | A server-side transport configuration failure prevents proxying. |
| `502`       | empty body   | none                                      | The MCP upstream is unavailable or unreachable.                  |

#### Client handling

* Do not retry `401` or `404` without changing the request.
* `500` and `502` should be treated as server-side failures.
* Retry `502` with backoff.

### Tool-Call Failures

Once a tool call begins, Terra-defined validation and query-construction failures surface as MCP tool errors.

#### Return contract

For tool-call failures, Terra guarantees the error detail string listed below.

The exact outer MCP error envelope is produced by the MCP runtime, so this document only guarantees the tool error detail text, not the full wrapper shape.

#### Guaranteed tool error details

**Query shape validation**

| Error detail                           | When it is returned                                        |
| -------------------------------------- | ---------------------------------------------------------- |
| `fields or select are required`        | Neither `fields` nor `select` was provided.                |
| `fields and select cannot both be set` | Both `fields` and `select` were provided in the same call. |

**Request context failures**

| Error detail                          | When it is returned                                               |
| ------------------------------------- | ----------------------------------------------------------------- |
| `request context is unavailable`      | The tool did not receive the request context required to execute. |
| `Provider-User-Id header is required` | The tool did not receive the required user context header.        |

These should be treated as server-side failures rather than malformed client input.

**Timestamp filter validation**

| Error detail                                                                   | When it is returned                                              |
| ------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| `Only the IN operator accepts a list of timestamps`                            | A timestamp filter used a list with an operator other than `IN`. |
| `IN timestamp filters require at least one timestamp`                          | A timestamp `IN` filter was empty.                               |
| `Invalid ISO 8601 timestamp '<value>'. Use formats like 2025-11-12T00:00:00Z.` | A timestamp value was not valid ISO 8601.                        |
| `Only timestamp fields support list values via IN`                             | A list value was provided for a non-timestamp field.             |

**Logical filter validation**

| Error detail                                        | When it is returned                                        |
| --------------------------------------------------- | ---------------------------------------------------------- |
| `And condition provided but empty after conversion` | An `and` clause contained no usable subconditions.         |
| `Or condition provided but empty after conversion`  | An `or` clause contained no usable subconditions.          |
| `Not condition was None after conversion`           | A `not` clause could not be converted into a valid filter. |

#### Client handling

* Do not retry tool-call validation failures without changing the tool input.
* Surface the returned detail string directly to developers.
* Treat request-context failures as server-side errors.

### What Is Not Guaranteed Here

This document intentionally does not guarantee:

* the full outer MCP error envelope for tool-call failures
* validation messages generated solely by the MCP runtime or model layer
* error messages for malformed requests that fail before reaching Terra's own validation logic

Only the statuses and detail strings listed above are guaranteed by Terra's implementation.
