Core Concepts

Errors

String Theory uses a consistent error format to help you understand and handle issues that might arise when using the system. Each error has a HTTP status, error type, and detailed information about what went wrong.

Retryable Errors

Retryable errors are errors that should be retried. Retryable errors can ultimately result in another error that is not retryable. It is often the case that whether or not an operation is retryable depends on the sources you were operating on. String Theory inspects the original sources to make its determinations on whether or not an error is marked as retryable.

400: Insufficient Funds

Status: 400 | Type: InsufficientFundsError | possibly retryable

This error occurs when attempting to withdraw more money than is available in the specified sources(s). The error will include details about the requested amount and the actual available balance in the data field as well as the overage amount that would have been overdrawn if the request was successful.

This error is retryable when the sources provided are groups, which can change over time. When attempting to withdraw from knots by id this error will be non-retryable as knots can never increase in value.

Error Data Fields:

Name
Type
Description
sourceBalancesBalance[]The balances of the provided sources
requestedAmountAmountThe amount that was requested to withdraw
overageAmountAmountThe amount that would have been overdrawn if the request was successful
View example error
{
  "status": 400,
  "message": "Insufficient Funds error occurred",
  "type": "InsufficientFundsError",
  "retryable": true,
  "name": "InsufficientFundsError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "sourceBalances": [
      {
        "amount": {
          "amount": 1000,
          "unitType": "currency_micros",
          "unitToken": "USD"
        },
        "knotIds": [
          "knot_01je9rzsd0f98bw334868nsh3z"
        ]
      }
    ],
    "requestedAmount": {
      "unitType": "currency_micros",
      "unitToken": "USD",
      "unitCount": 1000
    },
    "overageAmount": {
      "unitType": "currency_micros",
      "unitToken": "USD",
      "unitCount": 1000
    }
  }
}

400: Input Validation

Status: 400 | Type: InputValidationError | non-retryable

This error occurs when the input data fails validation checks. This could be due to invalid types, missing required fields, or values that don't meet the specified constraints. The error data will include details about what validation failed, including the field name, validation type, expected format, and the received invalid value. All of the fields are best effort and may not be present depending on the specific input failure.

Error Data Fields:

Name
Type
Description
pathstring[]The path to the field that failed validation
codestringThe validation error code (e.g. 'invalid_type', 'invalid_string')
messagestringA human readable message explaining why validation failed
expectedstringThe expected type or format
receivedstringThe actual value that was received
View example error
{
  "status": 400,
  "message": "Input Validation error occurred",
  "type": "InputValidationError",
  "retryable": false,
  "name": "InputValidationError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "path": "['input', 'requestedAmount']",
    "code": "invalid_type",
    "message": "Expected number, received string",
    "expected": "number",
    "received": "string"
  }
}

400: Invalid Amount

Status: 400 | Type: InvalidAmountError | non-retryable

This error occurs when the amount provided is invalid. Common reasons for this are:

  • A zero amount was provided. String Theory never stores 0 amounts, and in most cases will not allow them as input.
  • The unitType or unitToken of the amount does not match the amounts of the knots you are trying to operate on.

Error Data Fields:

Name
Type
Description
amountsAmount[]The amounts that were invalid
View example error
{
  "status": 400,
  "message": "Invalid Amount error occurred",
  "type": "InvalidAmountError",
  "retryable": false,
  "name": "InvalidAmountError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "amounts": [
      {
        "unitType": "currency_micros",
        "unitToken": "USD",
        "unitCount": 1000
      }
    ]
  }
}

404: Not Found

Status: 404 | Type: NotFoundError | non-retryable

This error occurs when a resource is not found.

Error Data Fields:

Name
Type
Description
missingIdsstring[]The IDs that could not be found
sourcesSourcesThe sources that could not be found
missingGroupsGroup[]The groups that could not be found
missingHoldsHold[]The holds that could not be found
View example error
{
  "status": 404,
  "message": "Not Found error occurred",
  "type": "NotFoundError",
  "retryable": false,
  "name": "NotFoundError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "missingIds": "['group_01je9rzsczfvgtx3p00s1stw69']",
    "sources": {
      "knotIds": [
        "knot_01je9rzsd0f98bw334868nsh3z"
      ],
      "threadIds": [
        "thread_01je9rzsd0f98bw334833d6en6"
      ],
      "groupUnions": [
        {
          "id": "group_01je9rzsczfvgtx3p00s1stw69"
        },
        {
          "type": "test_group",
          "token": "group_1"
        }
      ],
      "groupIntersections": [
        [
          {
            "id": "group_01je9rzsczfvgtx3p00s1stw69"
          }
        ],
        [
          {
            "type": "test_group",
            "token": "group_1"
          }
        ]
      ]
    },
    "missingGroups": [
      {
        "type": "test_group",
        "token": "group_1",
        "id": "group_01je9rzsczfvgtx3p00s1stw69"
      }
    ],
    "missingHolds": [
      {
        "id": "hold_9rz1je0scz69fvgtx3p00s1tw",
        "type": "test_hold",
        "token": "hold_1"
      }
    ]
  }
}

500: Stale Knot

Status: 500 | Type: StaleKnotError | possibly retryable

This error occurs when a knot is stale. Knots are immutable point-in-time snapshots of money, that become stale once any change has been made to them. Once they become stale they can never become current again.

This error is retryable when operating on groups, which can change over time and non-retryable when operating on knots by id since knots can never become current again once they are stale.

Error Data Fields:

Name
Type
Description
staleKnotIdsKnotId[]The knot ids that were stale
View example error
{
  "status": 500,
  "message": "Stale Knot error occurred",
  "type": "StaleKnotError",
  "retryable": true,
  "name": "StaleKnotError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "staleKnotIds": [
      "knot_01je9rzsd0f98bw334868nsh3z"
    ]
  }
}

500: Temporary Conflict

Status: 500 | Type: TemporaryConflictError | retryable

This error occurs when a temporary conflict is detected. This is the result of multiple calls racing for the same underlying knots. This error is only caused by incredibly tight race conditions and should always be retried. It may, however, ultimately result in another error that is not retryable

Error Data Fields:

Name
Type
Description
groupsGroupId[]The groups that were involved in the conflict
threadsThreadId[]The threads that were involved in the conflict
idempotencyIdempotencyInfoOptional information about the conflicting idempotent request
View example error
{
  "status": 500,
  "message": "Temporary Conflict error occurred",
  "type": "TemporaryConflictError",
  "retryable": true,
  "name": "TemporaryConflictError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "groups": [
      "group_01je9rzsczfvgtx3p00s1stw69"
    ],
    "threads": [
      "thread_01je9rzsd0f98bw334833d6en6"
    ],
    "idempotency": {
      "type": "payment",
      "token": "pmt_123",
      "ownerId": "usr_01je9rzsd0f98bw334833d6en6",
      "ownerType": "user",
      "method": "/loan/group",
      "version": "2"
    }
  }
}

500: Calculation Error

Status: 500 | Type: CalculationError | non-retryable

This error occurs when String Theory fails on an internal calculation. This only results from a bug in String Theory code, as any situations that would result in this error should be caught as invalid input. If you receive this error please report it to the String Theory team.

Error Data Fields:

Name
Type
Description
amountsAmount[]The amounts that were involved in the calculation
View example error
{
  "status": 500,
  "message": "Calculation Error error occurred",
  "type": "CalculationError",
  "retryable": false,
  "name": "CalculationError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "amounts": [
      {
        "unitType": "currency_micros",
        "unitToken": "USD",
        "unitCount": 1000
      }
    ]
  }
}

500: Invalid State

Status: 500 | Type: InvalidStateError | possibly retryable

This error occurs when you attempt to perform an action on a knot that is not allowed in its current state. This error is retryable when operating on groups, which can change over time. When operating on knots by id this error will be non-retryable as knots can never change state.

Error Data Fields:

Name
Type
Description
invalidKnotIdsKnotId[]The knot ids that were invalid
View example error
{
  "status": 500,
  "message": "Invalid State error occurred",
  "type": "InvalidStateError",
  "retryable": true,
  "name": "InvalidStateError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "invalidKnotIds": [
      "knot_01je9rzsd0f98bw334868nsh3z"
    ]
  }
}

500: Request Timeout

Status: 500 | Type: RequestTimeoutError | retryable

This error occurs when a request takes too long to process and times out. This can happen due to database transaction timeouts or overall request processing time limits being exceeded. This error is always retryable and should be attempted again, potentially with a backoff strategy.

Error Data Fields:

Name
Type
Description
reasonstringThe reason for the timeout ('database_transaction' or 'total_time')
View example error
{
  "status": 500,
  "message": "Request Timeout error occurred",
  "type": "RequestTimeoutError",
  "retryable": true,
  "name": "RequestTimeoutError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3",
  "data": {
    "reason": "string"
  }
}

500: Unknown

Status: 500 | Type: UnknownError | unknown

This error occurs when an something internal happened that String Theory itself does not understand. These should be rare and are the result of bugs in the String Theory code base. Please contact the String Theory team if you receive this error.

View example error
{
  "status": 500,
  "message": "Unknown error occurred",
  "type": "UnknownError",
  "name": "UnknownError",
  "traceId": "trace_01jf0p5c3jfk1bqf09nshpy1x3"
}