# Errors (Carbon 2.0)

> Every carbon_core::error::Error variant in Carbon 2.0.0 with its message, cause and fix, plus common errors from RPC, rustls and Cargo.

This page lists every variant of `carbon_core::error::Error` in Carbon 2.0.0 as **error → cause → fix**, followed by errors that come from Carbon's dependencies but show up in Carbon pipelines. For how errors flow through a pipeline, see [Error handling](https://carbon.sevenlabs.org/concepts/error-handling.md).

Source: [`crates/core/src/error.rs`](https://github.com/sevenlabs-hq/carbon/blob/v2.0.0/crates/core/src/error.rs).

## How Carbon reports errors

```rust
#[derive(Error, Debug)]
pub enum Error {
    #[error("Missing update type in datasource")]
    MissingUpdateTypeInDatasource(UpdateType),
    #[error("Failed to receive updates({0})")]
    FailedToReceiveUpdates(String),
    #[error("Transaction missing fee payer")]
    MissingFeePayer,
    #[error("Missing inner instructions")]
    MissingInnerInstructions,
    #[error("Missing account in transaction")]
    MissingAccountInTransaction,
    #[error("Missing instruction data")]
    MissingInstructionData,
    #[error("Failed to consume datasource ({0})")]
    FailedToConsumeDatasource(String),
    #[error("Custom error: {0}")]
    Custom(String),
}

pub type CarbonResult<T> = Result<T, Error>;
```

The pipeline logs errors with `{:?}`, so logs show the **Debug** form (`FailedToConsumeDatasource("Failed to fetch program accounts")`), not the `Display` message. Both forms are listed below. Where an error surfaces decides what happens next:

| Where it is returned                   | Log line (`error` level, target `carbon_core::pipeline`) | Effect                                                                                                                          |
| -------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `Datasource::consume`                  | `error consuming datasource: <Debug>`                    | That datasource stops. The others keep running. When none are left, the pipeline drains the channel and `run` returns `Ok(())`. |
| A decoder step or `Processor::process` | `error processing update (<update Debug>): <Debug>`      | The update is counted in `carbon_updates_failed_total`; the remaining pipes for that update are skipped; processing continues.  |
| A metrics exporter                     | none                                                     | `Pipeline::run` returns the error.                                                                                              |

> **Warning: A failed datasource does not fail the process.** `Pipeline::run` returns `Ok(())` after its last datasource returns an error, so a binary that ends with `.run().await` exits with status 0. Check the logs, or alert on `carbon_updates_received_total` staying flat.

Enable logs with a logger such as `env_logger` and `RUST_LOG=info` (Carbon's own messages are at `info`, `warn` and `error`).

## `FailedToConsumeDatasource`

**Error.** `Failed to consume datasource (<message>)`. Logged as `error consuming datasource: FailedToConsumeDatasource("<message>")`.

**Cause.** A datasource's `consume` could not start or continue. Built-in producers and their messages:

| Datasource                           | Messages                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| RPC GPA                              | `Failed to fetch program accounts` (any RPC or deserialization failure of `getProgramAccounts`, including rate limits and timeouts); `Failed to parse pubkey: …`; `Failed to decode account`                                                                                                                                         |
| Helius GPA V2                        | `HTTP request failed: …`, `Failed to parse response: …`, `RPC error: <message> (code: <code>)`, `Response missing context or value field`                                                                                                                                                                                            |
| Helius GTFA                          | `Failed to serialize request config: …`, `HTTP request failed: …`, `HTTP error <status>: <body>`, `Failed to parse response: …`, `RPC error: <message> (code: <code>)`, `Response missing result field`                                                                                                                              |
| Yellowstone gRPC, Helius LaserStream | The `tonic` or client error text when building the endpoint, setting `x_token`, or connecting (invalid URL, DNS, TLS, refused connection, bad token)                                                                                                                                                                                 |
| Validator snapshot                   | `Ledger directory does not exist: …`, `Genesis archive not found: …. Expected genesis.tar.bz2`, `No loadable full snapshot archive found in …`, `Failed to load bank forks from snapshot: …`, `Invalid snapshot: loaded bank has slot 0, …`, download errors such as `Failed to download <url> after 3 retries: …`, `Scan failed: …` |

**Fix.** Read the message after the variant name; it names the failing step.

1. For connection errors, check the endpoint URL and scheme (`https://` for TLS gRPC), the token, and network access.
2. For `Failed to fetch program accounts` on the public endpoint, add `filters` (such as a `dataSize` or `memcmp` on the discriminator) to `RpcProgramAccountsConfig`: unfiltered `getProgramAccounts` on large programs times out or is rejected. Use a paid RPC for large programs.
3. For snapshot errors, check the paths and that the archive matches the cluster.
4. Restart the pipeline, or wrap the datasource in your own retry loop: datasources don't restart themselves after `consume` returns.

**See also.** [Datasources](https://carbon.sevenlabs.org/datasources.md), [Load account state](https://carbon.sevenlabs.org/guides/load-account-state.md), [Load a snapshot](https://carbon.sevenlabs.org/guides/load-a-snapshot.md).

## `Custom`

**Error.** `Custom error: <message>`. Logged as `Custom("<message>")`.

**Cause.** A catch-all used by:

| Producer                                            | Message                                                                                                                                                                          |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| RPC block subscribe                                 | `Failed to create RPC subscribe client after 10 attempts: …`, `Failed to subscribe after 10 attempts: …`                                                                         |
| RPC program subscribe                               | `Failed to create RPC subscribe client after 10 attempts: …`, `Failed to subscribe after 10 attempts: …`                                                                         |
| Helius Atlas WebSocket                              | `Error creating Filters for the Helius WebSocket: accounts and transactions can't be both empty`, `Failed to create Helius client after … attempts: …`                           |
| `carbon_core::postgres` and generated Postgres code | The `sqlx` error text, or `out of range`, `invalid numeric string`, `value exceeds maximum for target type`, `invalid scale for i128`, `invalid sign/scale for unsigned integer` |
| Your code                                           | Anything you wrap, for example `Error::Custom(e.to_string())`                                                                                                                    |

The subscribe datasources wait 3 seconds between attempts.

**Fix.** For subscribe failures, read the wrapped error: `Method not found (-32601)` means the endpoint doesn't support the method (see [`blockSubscribe` is not supported](#method-not-found-for-blocksubscribe)); connection errors mean a wrong `wss://` URL or a blocked network. For Atlas, pass at least one account or transaction filter. For Postgres errors, see the [Postgres reference](https://carbon.sevenlabs.org/reference/postgres.md). In your own code, prefer `Custom` with a descriptive message over `unwrap`, so the pipeline logs the failure and continues.

**See also.** [Stream with RPC](https://carbon.sevenlabs.org/guides/stream-with-rpc.md), [Postgres](https://carbon.sevenlabs.org/guides/postgres.md).

## `MissingFeePayer`

**Error.** `Transaction missing fee payer`. Logged as `error processing update (Transaction(…)): MissingFeePayer`.

**Cause.** The pipeline converts each `TransactionUpdate` into `TransactionMetadata` and takes the fee payer from the first static account key of the message. The message has no account keys. Built-in datasources never send such transactions; it happens when a custom datasource builds a `VersionedTransaction` with an empty or default message.

**Fix.** Build `TransactionUpdate::transaction` from the full decoded transaction (for RPC, `EncodedTransaction::decode()` on a Base64 payload), not from `VersionedTransaction::default()`. The update is skipped and the pipeline continues.

**See also.** [`TransactionUpdate`](https://carbon.sevenlabs.org/reference/updates.md#transactionupdate), [Custom datasource](https://carbon.sevenlabs.org/guides/custom-datasource.md).

## `MissingAccountInTransaction`

**Error.** `Missing account in transaction`. Logged as `MissingAccountInTransaction`.

**Cause.** Returned only by the public helper `carbon_core::transformers::extract_account_metas(compiled_instruction, message)` when an account index points past the message's **static** account keys. The pipeline does not call this helper. It happens when you call it on a V0 transaction whose instruction uses accounts from an address lookup table, because the helper ignores `meta.loaded_addresses`.

**Fix.** Use the instruction the pipeline already built (`raw_instruction` in instruction processors, or `NestedInstruction::instruction`), whose accounts include lookup-table addresses. If you need the helper, append `meta.loaded_addresses.writable` and `readonly` to the keys yourself.

**See also.** [`InstructionProcessorInputType`](https://carbon.sevenlabs.org/reference/processor-inputs.md#instructionprocessorinputtype).

## `MissingUpdateTypeInDatasource`

**Error.** `Missing update type in datasource`. Logged as `MissingUpdateTypeInDatasource(<UpdateType>)`.

**Cause.** Nothing in Carbon 2.0.0 returns this variant. It is reserved for checking a datasource's `update_types()` against registered pipes, which the 2.0.0 pipeline does not do.

**Fix.** If you see it, it comes from your own code or a third-party crate; read that code. Carbon itself does not validate `update_types()`.

**See also.** [`UpdateType`](https://carbon.sevenlabs.org/reference/updates.md#updatetype).

## `FailedToReceiveUpdates`

**Error.** `Failed to receive updates(<message>)` (no space before the parenthesis). Logged as `FailedToReceiveUpdates("<message>")`.

**Cause.** Not returned anywhere in Carbon 2.0.0. Available for custom datasources that lose their upstream stream.

**Fix.** Read the wrapped message from the datasource that returned it. If you write a datasource, either variant is fine; `FailedToConsumeDatasource` is what the built-in ones use.

**See also.** [`Datasource`](https://carbon.sevenlabs.org/reference/traits.md#datasource).

## `MissingInnerInstructions`

**Error.** `Missing inner instructions`. Logged as `MissingInnerInstructions`.

**Cause.** Not returned anywhere in Carbon 2.0.0. When `meta.inner_instructions` is `None`, the pipeline treats the transaction as having no CPIs instead of failing.

**Fix.** If CPIs are missing from your processors, the source did not send inner instructions: for custom RPC datasources, request `transaction_details: Full`; for Yellowstone, use a full transaction subscription. See also [invalid inner instruction stack height](#invalid-inner-instruction-stack-height).

**See also.** [Instructions](https://carbon.sevenlabs.org/concepts/instructions.md).

## `MissingInstructionData`

**Error.** `Missing instruction data`. Logged as `MissingInstructionData`.

**Cause.** Not returned anywhere in Carbon 2.0.0.

**Fix.** Read the code that returned it; decoders signal "not mine" by returning `None`, not this error.

**See also.** [`InstructionDecoder`](https://carbon.sevenlabs.org/reference/traits.md#instructiondecoder).

## `ConversionError`

**Error.** A separate error type, `carbon_core::transformers::yellowstone::ConversionError` (behind carbon-core's `yellowstone` feature). Its variants and `Display` messages:

```text
MissingField(field)                       missing required protobuf field `<field>`
InvalidByteLength { field, expected, actual }  invalid byte length for `<field>`: expected <expected>, got <actual>
IntegerOutOfRange { field, value }        value <value> for `<field>` does not fit in a u8
InvalidEnum { field, value }              invalid enum value <value> for `<field>`
InvalidNumber { field, value }            invalid numeric value `<value>` for `<field>`
InvalidTransactionError(_)                failed to decode the protobuf transaction error with wincode
```

**Cause.** The Yellowstone and LaserStream datasources convert protobuf transactions with `create_tx_versioned` and `create_tx_meta`. A malformed or incompatible message fails the conversion. They log `Failed to create transaction meta: <Debug>` and skip that transaction; a failed `create_tx_versioned` skips the transaction silently.

**Fix.** Usually a server running a Yellowstone protocol version that doesn't match `yellowstone-grpc-proto` 12.7 (Carbon 2.0.0's pin). Check the provider's version. The pipeline continues with the next transaction.

**See also.** [Stream with Yellowstone](https://carbon.sevenlabs.org/guides/stream-with-yellowstone.md).

## Related errors

These errors don't come from `carbon_core::error::Error`, but readers hit them while running Carbon pipelines.

### `Method not found` for `blockSubscribe`

**Error.** With `RpcBlockSubscribe` on `wss://api.mainnet-beta.solana.com`:

```text
[2026-11-09T00:15:41Z ERROR carbon_rpc_block_subscribe_datasource] Failed to subscribe to block updates: SubscribeFailed { reason: "Method not found (-32601)", message: "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"Method not found\"},\"id\":1}" }
[2026-11-09T00:16:42Z ERROR carbon_core::pipeline] error consuming datasource: Custom("Failed to subscribe after 10 attempts: subscribe failed: Method not found (-32601)")
[2026-11-09T00:16:42Z INFO  carbon_core::pipeline] update_receiver closed, shutting down.
[2026-11-09T00:16:42Z INFO  carbon_core::pipeline] pipeline shutdown complete.
```

**Cause.** `blockSubscribe` is an unstable RPC method that validators only serve with `--rpc-pubsub-enable-block-subscription`. Solana's public endpoints don't enable it. The datasource retries 11 times, 3 seconds apart, then gives up, and the pipeline exits with status 0.

**Fix.** Use an RPC provider that supports `blockSubscribe`, or switch datasource: the [RPC transaction crawler](https://carbon.sevenlabs.org/datasources/rpc-transaction-crawler.md) works on the public endpoint for one program's history, and [Yellowstone gRPC](https://carbon.sevenlabs.org/guides/stream-with-yellowstone.md) or [Helius LaserStream](https://carbon.sevenlabs.org/guides/stream-with-laserstream.md) stream every block.

**See also.** [Stream with RPC](https://carbon.sevenlabs.org/guides/stream-with-rpc.md).

### `429 Too Many Requests`

**Error.** With the RPC transaction crawler (or GPA) on the public endpoint, at `RUST_LOG=debug`:

```text
[2026-11-09T00:18:44Z DEBUG solana_rpc_client::http_sender] Too many requests: server responded with Response { url: "https://api.mainnet-beta.solana.com/", status: 429, headers: {…, "retry-after": "10", …} }
```

and, once the client's own retries are exhausted, at `warn` and `error` level:

```text
[2026-11-09T00:19:39Z WARN  carbon_rpc_transaction_crawler_datasource] Failed to fetch transaction 2RPWo3shvDtwGNSD2tY79uwFJ6Gbx1M7g5knfsJEDpcdahojCL8csGJV6KCEyvzZC2UhBnctSPcFSwSPr4i4jHct (attempt 1/3), retrying in 1000ms: Error { request: Some(GetTransaction), kind: Reqwest(reqwest::Error { kind: Status(429, None), url: "https://api.mainnet-beta.solana.com/" }) }
```

**Cause.** The public endpoint rate-limits per IP. `solana-rpc-client` retries 429s internally (logged at `debug`), then the crawler retries with backoff (`RetryConfig::default()`: 3 retries, 1 s initial, ×2, 10 s max). After the last retry it logs `Failed to fetch transaction <sig> after 3 retries: …` and **skips that transaction**.

**Fix.**

1. Lower `ConnectionConfig::max_concurrent_requests` (default 5) and raise `polling_interval`.
2. Raise `RetryConfig::max_retries` and the backoff so fewer transactions are skipped.
3. For anything beyond a demo, use a paid RPC endpoint.

**See also.** [Backfill transactions](https://carbon.sevenlabs.org/guides/backfill-transactions.md), [RPC transaction crawler](https://carbon.sevenlabs.org/datasources/rpc-transaction-crawler.md).

### `Could not automatically determine the process-level CryptoProvider`

**Error.** At startup, with the Yellowstone gRPC or Helius LaserStream datasource and a TLS (`https://`) endpoint:

```text
thread 'tokio-rt-worker' panicked at /home/you/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.46/src/crypto/mod.rs:249:14:

Could not automatically determine the process-level CryptoProvider from Rustls crate features.
Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'aws-lc-rs' and 'ring' features is enabled.
See the documentation of the CryptoProvider type for more information.

[2026-11-09T00:51:58Z INFO  carbon_core::pipeline] update_receiver closed, shutting down.
[2026-11-09T00:51:58Z INFO  carbon_core::pipeline] pipeline shutdown complete.
```

**Cause.** The gRPC stack pulls in `rustls` 0.23 with both the `ring` and `aws-lc-rs` backends, so rustls can't pick one. The panic happens inside the datasource's task, so the pipeline logs a clean shutdown and exits with status 0.

**Fix.** Install a provider once at the start of `main`, before building the datasource:

`Cargo.toml`:

```toml
[dependencies]
rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs"] }
```

`src/main.rs`:

```rust
rustls::crypto::aws_lc_rs::default_provider()
    .install_default()
    .expect("failed to install the rustls crypto provider");
```

**See also.** [Stream with Yellowstone](https://carbon.sevenlabs.org/guides/stream-with-yellowstone.md), [Stream with LaserStream](https://carbon.sevenlabs.org/guides/stream-with-laserstream.md).

### `there are multiple different versions of crate carbon_core`

**Error.** At compile time, when a Carbon 1.x crate is mixed with Carbon 2.0.0:

```text
error[E0277]: the trait bound `for<'a> MemoProgramDecoder: InstructionDecoder<'a>` is not satisfied
   --> src/main.rs:19:53
    |
 19 |     let _pipeline = Pipeline::builder().instruction(MemoProgramDecoder, Memos).build()?;
    |                                         ----------- ^^^^^^^^^^^^^^^^^^ the trait `for<'a> InstructionDecoder<'a>` is not implemented for `MemoProgramDecoder`
    |                                         |
    |                                         required by a bound introduced by this call
    |
note: there are multiple different versions of crate `carbon_core` in the dependency graph
   --> /home/you/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/carbon-core-2.0.0/src/instruction.rs:187:1
    |
187 | pub trait InstructionDecoder<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is the expected trait
    |
   ::: /home/you/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/carbon-core-1.0.0/src/instruction.rs:188:1
    |
188 | pub trait InstructionDecoder<'a> {
    | -------------------------------- this is the found trait
```

**Cause.** Here `carbon-memo-program-decoder = "1.0.0"` sits next to `carbon-core = "2.0.0"`, so two `carbon_core` crates are compiled and the decoder implements the 1.x trait. The same happens with Solana types: Carbon 1 uses the Solana 3 crates (`solana-account` 3, `solana-transaction-status` 3) and Carbon 2 the Agave 4.2 cohort (`solana-account` 4.3, `solana-transaction-status` 4.2), so you get `expected Account, found a different Account` with a "multiple different versions of crate `solana_account`" note. `Pubkey` is the exception: `solana-pubkey` 3 and 4 are the same type, so pubkeys don't trigger it.

**Fix.**

1. Set every Carbon crate in `Cargo.toml` to `2.0.0`.
2. Set direct Solana dependencies to the versions Carbon 2.0.0 pins (for example `solana-account = "4.3.2"`, `solana-instruction = "3.4.1"`, `solana-pubkey = "4.2.1"`, `solana-client = "=4.2.2"`).
3. Find the stray crate with `cargo tree -i carbon-core@1.0.0` (or `-i solana-account@3.0.0`).
4. Regenerate decoders produced by an older CLI with `@sevenlabs-hq/carbon-cli@2.0.0`. `carbon-jetstreamer-datasource` and `carbon-jito-shredstream-grpc-datasource` have no 2.0 release; don't use them with Carbon 2.

**See also.** [Migrate to v2](https://carbon.sevenlabs.org/guides/migrate-to-v2.md), [Installation](https://carbon.sevenlabs.org/installation.md).

### `Failed to decode transaction` with `Json` encoding

**Error.** With `RpcBlockSubscribe` or `RpcBlockCrawler` configured with `UiTransactionEncoding::Json` or `JsonParsed`, every transaction logs:

```text
ERROR carbon_rpc_block_subscribe_datasource] Failed to decode transaction: EncodedTransactionWithStatusMeta { transaction: Json(UiTransaction { … }), … }
```

**Cause.** Carbon rebuilds the binary transaction with `EncodedTransaction::decode()`, which only works for binary encodings. JSON payloads can't be decoded, so each transaction is skipped and no instruction processor runs.

**Fix.** Request a binary encoding and V1 support in the config you pass:

```rust
RpcBlockSubscribeConfig {
    encoding: Some(UiTransactionEncoding::Base64),
    transaction_details: Some(TransactionDetails::Full),
    max_supported_transaction_version: Some(1),
    ..RpcBlockSubscribeConfig::default()
}
```

Use the same fields on `RpcBlockConfig` for the block crawler. The transaction crawler and Helius GTFA set Base64 and V1 themselves.

**See also.** [Stream with RPC](https://carbon.sevenlabs.org/guides/stream-with-rpc.md), [Migrate to v2](https://carbon.sevenlabs.org/guides/migrate-to-v2.md).

### `Full(..)` when sending updates

**Error.** One of:

```text
ERROR carbon_yellowstone_grpc_datasource] Failed to send transaction update with signature … at slot …: "Full(..)"
WARN  carbon_rpc_transaction_crawler_datasource] Failed to send update: "Full(..)"
ERROR carbon_rpc_block_crawler_datasource] Error sending transaction update: "Full(..)"
```

**Cause.** The pipeline's update channel is full because processors are slower than the source, and the datasource uses `try_send`, which drops the update instead of waiting. Yellowstone, LaserStream, Helius Atlas, RPC block subscribe, RPC block crawler, RPC program subscribe and (by default) the RPC transaction crawler all drop updates this way. Block subscribe and block crawler also stop sending the rest of that block.

**Fix.**

1. Raise [`channel_buffer_size`](https://carbon.sevenlabs.org/reference/pipeline-builder.md#channel_buffer_size) (default 1,000).
2. Make processors faster, or move slow work (database writes, HTTP calls) to a spawned task or a batch.
3. For the transaction crawler, set `ConnectionConfig::blocking_send = true` to apply backpressure instead of dropping.
4. Watch the `carbon_updates_queued` gauge.

**See also.** [Production](https://carbon.sevenlabs.org/guides/production.md), [Metrics reference](https://carbon.sevenlabs.org/reference/metrics.md).

### Invalid inner instruction stack height

**Error.**

```text
WARN  carbon_core::transformers] invalid inner instruction stack height (None) in transaction <signature> at instruction <index>, dropping the remaining inner instructions of this group
```

**Cause.** The source sent inner instructions without a `stack_height` (old transactions, or providers that strip it), or with a height outside 2 to 5. Carbon needs the height to rebuild the CPI tree, so it drops the rest of that instruction's inner instructions. Their instruction processors don't run.

**Fix.** Use a source that reports `stackHeight` (current RPC nodes and Yellowstone do). For historical data from before stack heights were recorded, decode inner instructions yourself from `meta.inner_instructions` in a transaction processor.

**See also.** [Instructions](https://carbon.sevenlabs.org/concepts/instructions.md).

### Ctrl-C does not stop the pipeline

**Error.** The process keeps running after Ctrl-C, usually under load.

**Cause.** `Pipeline::run` only listens for Ctrl-C between updates and installs a handler that replaces the default exit, so a signal that arrives while a processor runs is lost.

**Fix.** Handle Ctrl-C yourself and cancel a token passed to [`datasource_cancellation_token`](https://carbon.sevenlabs.org/reference/pipeline-builder.md#datasource_cancellation_token). See [Ctrl-C is ignored while an update is processing](https://carbon.sevenlabs.org/reference/pipeline-builder.md#ctrl-c-is-ignored-while-an-update-is-processing).

**See also.** [Shutdown](https://carbon.sevenlabs.org/concepts/shutdown.md).

---

Carbon 2.0.0 documentation · Web: https://carbon.sevenlabs.org/reference/errors · Last updated 2026-11-09 · Index of all pages: https://carbon.sevenlabs.org/llms.txt
