Skip to main content

forest/chain/store/
errors.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use std::{borrow::Cow, fmt::Debug};
5
6use crate::blocks::CreateTipsetError;
7use crate::prelude::*;
8use cid::Error as CidErr;
9use fil_actors_shared::fvm_ipld_amt::Error as AmtErr;
10use fvm_ipld_encoding::Error as EncErr;
11use thiserror::Error;
12use tokio::task::JoinError;
13
14/// Chain error
15#[derive(Debug, Error)]
16pub enum Error {
17    /// Key was not found
18    #[error("Invalid tipset: {0}")]
19    UndefinedKey(String),
20    /// Key not found in database
21    #[error("{0} not found")]
22    NotFound(Cow<'static, str>),
23    /// Error originating constructing blockchain structures
24    #[error(transparent)]
25    Blockchain(#[from] CreateTipsetError),
26    /// Error originating from encoding arbitrary data
27    #[error("{0}")]
28    Encoding(String),
29    /// Error originating from Cid creation
30    #[error(transparent)]
31    Cid(#[from] CidErr),
32    /// Amt error
33    #[error("State error: {0}")]
34    State(Cow<'static, str>),
35    /// Requested height is a null round (no tipset), reported when resolving with
36    /// [`super::index::ResolveNullTipset::Fail`]. The Eth layer translates this into its own
37    /// Lotus-compatible message, so this internal phrasing is intentionally distinct.
38    #[error("null round at epoch {0}")]
39    NullRound(ChainEpoch),
40    #[error("height {0} is negative")]
41    NegativeHeight(ChainEpoch),
42    #[error("lookback height {lookback_height} is at or after base height {base_height}")]
43    LookbackHeightOverflow {
44        lookback_height: ChainEpoch,
45        base_height: ChainEpoch,
46    },
47    /// Other chain error
48    #[error("{0}")]
49    Other(String),
50}
51
52impl From<EncErr> for Error {
53    fn from(e: EncErr) -> Error {
54        Error::Encoding(e.to_string())
55    }
56}
57
58impl From<AmtErr> for Error {
59    fn from(e: AmtErr) -> Error {
60        Error::state(e.to_string())
61    }
62}
63
64impl From<String> for Error {
65    fn from(e: String) -> Self {
66        Error::Other(e)
67    }
68}
69
70impl From<anyhow::Error> for Error {
71    fn from(e: anyhow::Error) -> Self {
72        Error::Other(format!("{e:#}"))
73    }
74}
75
76impl From<std::io::Error> for Error {
77    fn from(e: std::io::Error) -> Self {
78        Error::Other(e.to_string())
79    }
80}
81
82impl<T> From<flume::SendError<T>> for Error {
83    fn from(e: flume::SendError<T>) -> Self {
84        Error::Other(e.to_string())
85    }
86}
87
88impl From<JoinError> for Error {
89    fn from(e: JoinError) -> Self {
90        Error::Other(format!("failed joining on tokio task: {e}"))
91    }
92}
93
94impl Error {
95    pub fn state(msg: impl Into<Cow<'static, str>>) -> Self {
96        Self::State(msg.into())
97    }
98}