Skip to content

Commit

Permalink
Added code blocks (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
briwylde08 authored Aug 30, 2022
1 parent a5573ba commit 67bf9d8
Showing 1 changed file with 65 additions and 4 deletions.
69 changes: 65 additions & 4 deletions docs/encyclopedia/error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
title: Error Handling
---

import { CodeExample } from "@site/src/components/CodeExample"

It’s important to anticipate errors your users may encounter as you develop on Stellar. In many tutorials throughout our developer documentation, we leave out error handling code to focus on the example. In this section, we will do the opposite and talk specifically about the errors.

By the end of this section, you should be able to categorize errors and understand the best way to handle them in your application.
Expand All @@ -28,8 +30,18 @@ Let’s get into these strategies in more detail. We will mainly focus on the tr
#### Queries
Many `GET` requests have specific parameter requirements, and while the SDKs can help enforce them, you can still pass invalid arguments (for example, an asset string that isn’t SEP-11 compatible) that error out every time. In this scenario, there’s nothing you can do aside from following the API specification. The `extras` field of the error response will often clue you in on where to look and what to look for.

[insert code]
<CodeExample>

```bash
curl -s https://horizon-testnet.stellar.org/claimable_balances/0000 | jq '.extras'
{
"invalid_field": "id",
"reason": "Invalid claimable balance ID"
}
```

</CodeExample>

Note that the SDKs make it a point to distinguish an invalid request (as above) versus a missing resource (a `404 Not Found`) (for example, the generic `NetworkError` versus a `NotFoundError` in the JavaScript SDK), where the latter might not be considered an error depending on your situation.

#### Transaction submissions
Expand All @@ -53,9 +65,39 @@ There are only two possible results to this scenario: either the transaction mak

Example implementation:

[insert code]
<CodeExample>

```js
let server = sdk.Server("horizon.stellar.org");

function submitTransaction(tx, timeout) {
if (!tx.timeBounds || tx.timeBounds.maxTime === 0) {
throw new Error("Always set a reasonable timebound!");
}
const expiration = parseInt(tx.timeBounds.maxTime);

return server.submitTransaction(tx).catch(function (error) {
if (isNonRetryErrorCase(error)) {
// ...do other error handling...
return;
}

// the tx no longer has a chance of making it into a ledger
if (Date.now() >= expiration) {
return new Error("The transaction timed out.");
}

timeout = timeout || 1; // start the (linear) back-off process
return sleep(timeout).then(function () {
return submitTransaction(tx, timeout + 5);
});
});
}
```

</CodeExample>

(We assume the existence of a sleep implementation similar to the one [here](https://stackoverflow.com/a/39914235)
We assume the existence of a sleep implementation similar to the one [here](https://stackoverflow.com/a/39914235)
Be sure to integrate backoff into your retry mechanism. In our example error-handling code above, we implement a simple linear backoff, but there are [plenty of recommendations](https://backoff-utils.readthedocs.io/en/latest/strategies.html#why-are-backoff-strategies-useful) for various other strategies. Backoff is important both for maintaining performance and avoiding rate-limiting issues.

### Adjusting the transaction- unsafe transaction adjustments strategy
Expand All @@ -66,7 +108,26 @@ Example scenario: invalid sequence numbers

These errors typically occur when you have an outdated view of an account. This could be because multiple devices are using this account, you have concurrent submissions happening, or other reasons. The solution is relatively simple: retrieve the account details and try again with an updated sequence number.

[insert code]
<CodeExample>

```js
// suppose `account` is an outdated `AccountResponse` object
let tx = sdk.TransactionBuilder(account, ...)/* etc */.build()
server.submitTransaction(tx).catch(function (error)) {
if (error.response && error.status == 400 && error.extras &&
error.extras.result_codes.transaction == sdk.TX_BAD_SEQ) {
return server.accounts()
.accountId(account.accountId())
.then(function (response) {
let tx = sdk.TransactionBuilder(response, ...)/* etc */.build()
return server.submitTransaction(tx);
});
}
// ...other error conditions...
}
```
</CodeExample>
Despite the solution’s simplicity, things can go wrong fast if you don’t understand why the error occurred.
Expand Down

0 comments on commit 67bf9d8

Please sign in to comment.