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
Section titled “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.
Error Types
Section titled “Error Types”Insufficient Funds
Section titled “Insufficient Funds”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
sourceBalances | Balance[] | The balances of the provided sources |
requestedAmount | Amount | The amount that was requested to withdraw |
overageAmount | Amount | The 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 } } }
Input Validation
Section titled “Input Validation”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
path | string[] | The path to the field that failed validation |
code | string | The validation error code (e.g. ‘invalid_type’, ‘invalid_string’) |
message | string | A human readable message explaining why validation failed |
expected | string | The expected type or format |
received | string | The 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" } }
Invalid Amount
Section titled “Invalid Amount”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
amounts | Amount[] | 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 } ] } }
Not Found
Section titled “Not Found”404 : Not Found
Status: 404 | Type: NotFoundError | non-retryable
This error occurs when a resource is not found.
Error Data Fields:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
missingIds | string[] | The IDs that could not be found |
sources | Sources | The sources that could not be found |
missingGroups | Group[] | The groups that could not be found |
missingHolds | Hold[] | 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" } ] } }
Stale Knot
Section titled “Stale Knot”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
staleKnotIds | KnotId[] | 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" ] } }
Temporary Conflict
Section titled “Temporary Conflict”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
groups | GroupId[] | The groups that were involved in the conflict |
threads | ThreadId[] | The threads that were involved in the conflict |
idempotency | IdempotencyInfo | Optional 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" } } }
Calculation Error
Section titled “Calculation Error”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
amounts | Amount[] | 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 } ] } }
Invalid State
Section titled “Invalid State”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
invalidKnotIds | KnotId[] | 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" ] } }
Request Timeout
Section titled “Request Timeout”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:
Section titled “Error Data Fields:”Name | Type | Description |
---|---|---|
reason | string | The 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": "database_transaction" } }
Unknown
Section titled “Unknown”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" }