# Errors

Error codes returned by the Twisp API when things don't go right.

Source: https://www.twisp.com/docs/reference/api/errors

This reference lists the types of errors that may be encountered.

## Error Responses

The API uses a response format conforming to the [GraphQL spec](https://spec.graphql.org/October2021/#sec-Response-Format). For more information, see the docs on [Response Format](/docs/reference/api/response-format).

> If the request raised any errors, the response map must contain an entry with key `errors`. The value of this entry is described in the “Errors” section. If the request completed without raising any errors, this entry must not be present.

Because the Twisp API supports [Transactional Operations](/docs/reference/api/transactional-operations), if there are _any_ errors, then the entire operation is aborted and the `"data"` field will be `null`.

## Example Response

This example shows the response of an `createAccount` operation with a malformed `accountId`.

**Request**

```graphql
mutation INVALID_UUID_LENGTH {
  createAccount(
    input: {
      accountId: ""
      code: "TEST"
      name: "TEST"
      normalBalanceType: DEBIT
      status: ACTIVE
    }
  ) {
    accountId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: createAccount.input.accountId invalid UUID length: 0",
      "path": ["createAccount", "input", "accountId"],
      "extensions": {
        "code": "UUID_PARSE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

The response indicates that there was an error with the `createAccount` mutation request. The error is a `UUID_PARSE_ERROR`, which means that the `accountId` field in the request has an invalid UUID value.

Within the `errors` array, each error object contains fields specifying more information about the error:

- `message` summarizes the error, and may give a clue to its cause. In this example, it indicates that the `accountId` field has an invalid length, which is 0.
- `path` specifies the location within the GraphQL operation that the error occurred. In this example, it indicates that the error occurred in the `accountId` field of the `input` argument provided to the `createAccount` mutation.
- `extensions` provides additional information about the error.
- `extensions.code` specifies the **error code** used to represent the error. In this example, the code is `UUID_PARSE_ERROR`.

The `data` field in the response is `null` since the request was not successful due to the error.

To resolve this particular error, a valid UUID value should be provided for the `accountId` field. An empty string is not a valid UUID value.

## Error Codes

### ACCESS_DENIED
Indicates that the request was denied due to a lack of proper authentication or authorization.

### ALREADY_EXISTS
Indicates that the requested resource already exists and cannot be created again.

### BAD_REQUEST
Indicates that the request was malformed or invalid.

For example, a missing `eq` in the partition key:
**Request**

```graphql
query EqRequiredForPartitionKey {
  accounts(
    index: { name: ACCOUNT_ID }
    where: { accountId: { like: "foo" } }
    first: 10
  ) {
    nodes {
      accountId
      name
    }
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: accounts eq required for account_id partition key",
      "path": ["accounts"],
      "extensions": {
        "code": "BAD_REQUEST",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

Or a missing partition key:
**Request**

```graphql
query PartitionKeyRequired {
  accounts(
    index: { name: ACCOUNT_ID }
    where: { name: { eq: "TESTACCT" } }
    first: 10
  ) {
    nodes {
      accountId
      name
    }
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: accounts account_id partition key required",
      "path": ["accounts"],
      "extensions": {
        "code": "BAD_REQUEST",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### CEL_EVALUATION_ERROR
Indicates that there was an error evaluating a CEL expression.

### DATE_PARSE_ERROR
Indicates that there was an error parsing a date string.
**Request**

```graphql
mutation DATE_PARSE_ERROR {
  postTransaction(
    input: {
      transactionId: "981b7bbd-2d70-4975-90d3-027ee9d8be77"
      tranCode: "TESTTC"
      params: {
        accountId: "7052f9fd-dd15-40d0-b0b6-df8c4c372e41"
        effectiveDate: "{2022-12-21}"
      }
    }
  ) {
    transactionId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: postTransaction parsing time \"{2022-12-21}\" as \"2006-01-02\": cannot parse \"{2022-12-21}\" as \"2006\"",
      "path": ["postTransaction"],
      "extensions": {
        "code": "DATE_PARSE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### DEPENDENCY_ERROR
Indicates that there was an error with a dependent resource.
**Request**

```graphql
mutation DEPENDENCY_ERRORS {
  missingRequiredParam: postTransaction(
    input: {
      transactionId: "f82391bb-90a7-4328-b5ad-8629a7602de8"
      tranCode: "TESTTC"
      params: { accountId: "7052f9fd-dd15-40d0-b0b6-df8c4c372e41" }
    }
  ) {
    transactionId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: missingRequiredParam param 'effectiveDate' not defined",
      "path": ["missingRequiredParam"],
      "extensions": {
        "code": "DEPENDENCY_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### ENUM_PARSE_ERROR
Indicates that there was an error parsing an enumeration value.
**Request**

```graphql
query GetJournalsInvalidStatus {
  journals(
    index: { name: STATUS }
    where: { status: { eq: "FOO" } }
    first: 100
  ) {
    nodes {
      name
      status
      created
    }
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: journals journal status enum 'FOO' not found",
      "path": ["journals"],
      "extensions": {
        "code": "ENUM_PARSE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### FOREIGN_KEY_VIOLATION
Indicates that there was an error with a foreign key constraint.

### GRAPHQL_PARSE_FAILED
Indicates that there was an error parsing the GraphQL query.
**Request**

```graphql
mutation 82*
```
**Response**

```json
{
  "errors": [
    {
      "message": "Expected {, found Int",
      "locations": [{ "line": 1, "column": 10 }],
      "extensions": { "code": "GRAPHQL_PARSE_FAILED", "retriableError": false }
    }
  ],
  "data": null
}
```

### GRAPHQL_VALIDATION_FAILED
Indicates that there was an error validating the GraphQL query.
**Request**

```graphql
query first_should_be_int {
  accounts(first: "10") {
    nodes {
      accountId
    }
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "Int cannot represent non-integer value: \"10\"",
      "locations": [{ "line": 2, "column": 20 }],
      "extensions": {
        "code": "GRAPHQL_VALIDATION_FAILED",
        "retriableError": false
      }
    },
    {
      "message": "Field \"accounts\" argument \"index\" of type \"AccountIndexInput!\" is required, but it was not provided.",
      "locations": [{ "line": 2, "column": 3 }],
      "extensions": {
        "code": "GRAPHQL_VALIDATION_FAILED",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### INTERNAL_SERVER_ERROR
Indicates that there was an error on the server that prevented it from fulfilling the request.

### INTERRUPTED
Indicates that the request was interrupted.

### JSON_PARSE_ERROR
Indicates that there was an error parsing a JSON string.
**Request**

```graphql
mutation JSON_PARSE_ERROR {
  invalidParams: postTransaction(
    input: {
      transactionId: "e0995c6f-1a25-42f2-b2f2-568cf91f0487"
      tranCode: "TESTTC"
      params: ""
    }
  ) {
    transactionId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: invalidParams.input.params invalid JSON format",
      "path": ["invalidParams", "input", "params"],
      "extensions": {
        "code": "JSON_PARSE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### NOT_FOUND
Indicates that the requested resource was not found.

### NOT_SUPPORTED
Indicates that the requested operation is not supported.

### TIMESTAMP_PARSE_ERROR
Indicates that there was an error parsing a timestamp.

### TRAN_CODE_ERROR
Indicates that there was an error with a transaction code.

For example, with unbalanced entries:
**Request**

```graphql
mutation CreateTranCode {
  createTranCode(
    input: {
      tranCodeId: "74e90f0a-5ffa-4fce-9880-1bc976b59937"
      code: "TFR_TEST"
      description: "Transfer $1 from one account to another"
      params: [
        { name: "effectiveDate", type: DATE }
        {
          name: "fromAccount"
          type: UUID
          description: "Account to send funds from."
        }
        {
          name: "toAccount"
          type: UUID
          description: "Recipient account. Required."
        }
        { name: "amount", type: DECIMAL, default: "1.00" }
      ]
      transaction: {
        journalId: "uuid('822cb59f-ce51-4837-8391-2af3b7a5fc51')"
        effective: "params.effectiveDate"
      }
      entries: [
        {
          accountId: "params.fromAccount"
          units: "params.amount"
          currency: "'USD'"
          description: "metadata.tags + ' from'"
          entryType: "'TRANSFER_DR'"
          direction: "DEBIT"
          layer: "SETTLED"
        }
      ]
      metadata: { tags: "xfer" }
    }
  ) {
    tranCodeId
    code
    transaction {
      effective
    }
    entries {
      accountId
      units
      entryType
      direction
      layer
    }
    metadata
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: createTranCode 'TFR_TEST' tran code entries unbalanced: 'DR 1.00 USD != 'CR 0 USD'",
      "path": ["createTranCode"],
      "extensions": {
        "code": "TRAN_CODE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

Another example, with a syntax error:
**Request**

```graphql
mutation TRAN_CODE_ERROR {
  # Invalid CEL syntax in transaction.effective
  tc1: createTranCode(
    input: {
      tranCodeId: "B852FEA6-3445-49E7-BFD4-A162EEC08017"
      code: "ABC123"
      description: "an example tran code"
      params: [{ name: "amount", type: DECIMAL }]
      transaction: {
        effective: "{time.Now()}"
        journalId: "uuid('822cb59f-ce51-4837-8391-2af3b7a5fc51')"
      }
      entries: [
        {
          entryType: "EXAMPLE"
          accountId: "uuid('7052f9fd-dd15-40d0-b0b6-df8c4c372e41')"
          layer: "SETTLED"
          units: "params.amount"
          currency: "'USD'"
          direction: DEBIT
        }
      ]
    }
  ) {
    code
    status
  }

  # Invalid CEL syntax in transaction.journalId
  tc2: createTranCode(
    input: {
      tranCodeId: "B852FEA6-3445-49E7-BFD4-A162EEC08018"
      code: "DEF456"
      description: "an example tran code"
      params: [{ name: "amount", type: DECIMAL }]
      transaction: {
        effective: "time.Now()"
        journalId: "822cb59f-ce51-4837-8391-2af3b7a5fc51"
      }
      entries: [
        {
          entryType: "EXAMPLE"
          accountId: "uuid('7052f9fd-dd15-40d0-b0b6-df8c4c372e41')"
          layer: "SETTLED"
          units: "params.amount"
          currency: "'USD'"
          direction: DEBIT
        }
      ]
    }
  ) {
    code
    status
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: tc1 [effective]: `{time.Now()}`, ERROR: <input>:1:12: Syntax error: mismatched input '}' expecting ':'\n | {time.Now()}\n | ...........^",
      "path": ["tc1"],
      "extensions": {
        "code": "TRAN_CODE_ERROR",
        "retriableError": false
      }
    },
    {
      "message": "input: tc2 [journal_id]: `822cb59f-ce51-4837-8391-2af3b7a5fc51`, ERROR: <input>:1:4: Syntax error: mismatched input 'cb59f' expecting <EOF>\n | 822cb59f-ce51-4837-8391-2af3b7a5fc51\n | ...^",
      "path": ["tc2"],
      "extensions": {
        "code": "TRAN_CODE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```

### TRANSACTION_ERROR
Indicates that there was an error with a transaction.

### UNIQUE_CONSTRAINT_VIOLATION
Indicates that there was an error with a unique constraint.
**Request**

```graphql
mutation UNIQUE_CONSTRAINT_VIOLATION {
  # Account already exists
  createAccount(
    input: {
      accountId: "7052f9fd-dd15-40d0-b0b6-df8c4c372e41"
      code: "DUP_TESTACCT"
      name: "DUP_TESTACCT"
      normalBalanceType: DEBIT
      status: ACTIVE
    }
  ) {
    accountId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: createAccount unique constraint violation\nAccount.indexes.account_id unique constraint violation",
      "path": ["createAccount"],
      "extensions": {
        "action": "",
        "code": "UNIQUE_CONSTRAINT_VIOLATION",
        "path": "system.Account",
        "retriableError": false,
        "system": ["full_access_auth", "tx"]
      }
    }
  ],
  "data": null
}
```

### UNKNOWN_ERROR
Indicates that an unknown error occurred.

For example, an `unknown error` occuring when selecting accounts
```json
{
  "errors": [
    {
      "message": "input: accounts unknown error",
      "path": [
        "accounts"
      ],
      "extensions": {
        "code": "UNKNOWN_ERROR",
        "retriableError": true
      }
    }
  ],
  "data": null
}
```

### UUID_PARSE_ERROR
Indicates that there was an error parsing a UUID.
**Request**

```graphql
mutation INVALID_UUID_LENGTH {
  createAccount(
    input: {
      accountId: ""
      code: "TEST"
      name: "TEST"
      normalBalanceType: DEBIT
      status: ACTIVE
    }
  ) {
    accountId
  }
}
```
**Response**

```json
{
  "errors": [
    {
      "message": "input: createAccount.input.accountId invalid UUID length: 0",
      "path": ["createAccount", "input", "accountId"],
      "extensions": {
        "code": "UUID_PARSE_ERROR",
        "retriableError": false
      }
    }
  ],
  "data": null
}
```
