---
title: Error Handling and Return Codes
description: Handle success, revert codes, syscall statuses, and CPI error
  channels consistently in Thru C programs.
source_url:
  html: https://thru.org/docs/sdks/c-reference/error-handling-and-return-codes/
  md: https://thru.org/docs/sdks/c-reference/error-handling-and-return-codes.md
---

# Error Handling and Return Codes

Use this page when you need one compact reference for how success and failure are represented in the C SDK.

## Success baseline

`TSDK_SUCCESS` is the canonical success code and is defined as `0UL`.

Use it for:

- successful `tsdk_return(...)`
- success checks after most syscalls
- success checks on the callee error channel returned through `tsys_invoke`

## Local program failure

Use `tsdk_revert(error_code)` when your program detects an invalid condition and wants to terminate with a local error.

Typical examples:

- instruction payload too short
- invalid account index
- unexpected instruction tag
- failed precondition before a syscall

## Successful termination

Use `tsdk_return(return_code)` when the program has completed successfully and wants to exit.

In most application-level code, the return code should be `TSDK_SUCCESS`.

## Syscall error pattern

Most syscalls return a single `ulong` status:

```c
ulong rc = tsys_account_resize( account_idx, 128UL );
if( rc != TSDK_SUCCESS ) tsdk_revert( rc );
```

## CPI error pattern

`tsys_invoke` returns two different statuses:

- return value: syscall-level result
- `invoke_err_code`: callee-level result

Use both:

```c
ulong invoke_err = 0UL;
ulong invoke_result = tsys_invoke( payload, payload_sz, target_program_idx, NULL, &invoke_err );

if( invoke_result != TSDK_SUCCESS ) tsdk_revert( invoke_result );
if( invoke_err    != TSDK_SUCCESS ) tsdk_revert( invoke_err );
```

## Wrapper-level CPI validation failures

The current C wrapper can revert before issuing the CPI syscall if the auth descriptor is malformed or invalid.

Examples include:

- bad auth magic
- invalid account indices in auth or deauth lists
- auth entries for accounts not owned by the current program

## Recommended error strategy

| Situation | Recommended handling |
| - | - |
| Bad instruction layout | Revert with a local program error code. |
| Invalid index or ownership | Revert with a local program error code. |
| Failed syscall | Revert with the syscall return code, unless you intentionally remap it. |
| Failed CPI callee | Revert with `invoke_err`, unless you intentionally remap it. |

## Notes

- Do not mix up program-level validation errors with runtime or syscall return codes.
- Do not ignore the second result channel from `tsys_invoke`.
- Prefer a small local error-code namespace per program for validation failures, then bubble up syscall and CPI runtime codes directly when that is the clearest behavior.
