subxt_codegen/
error.rs

1// Copyright 2019-2025 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! Errors that can be emitted from codegen.
6
7use proc_macro2::{Span, TokenStream as TokenStream2};
8use scale_typegen::TypegenError;
9
10/// Error returned when the Codegen cannot generate the runtime API.
11#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum CodegenError {
14    /// Cannot decode the metadata bytes.
15    #[error("Could not decode metadata, only V14 and V15 metadata are supported: {0}")]
16    Decode(#[from] codec::Error),
17    /// Out of line modules are not supported.
18    #[error(
19        "Out-of-line subxt modules are not supported, make sure you are providing a body to your module: pub mod polkadot {{ ... }}"
20    )]
21    InvalidModule(Span),
22    /// Invalid type path.
23    #[error("Invalid type path {0}: {1}")]
24    InvalidTypePath(String, syn::Error),
25    /// Metadata for constant could not be found.
26    #[error(
27        "Metadata for constant entry {0}_{1} could not be found. Make sure you are providing a valid substrate-based metadata"
28    )]
29    MissingConstantMetadata(String, String),
30    /// Metadata for storage could not be found.
31    #[error(
32        "Metadata for storage entry {0}_{1} could not be found. Make sure you are providing a valid substrate-based metadata"
33    )]
34    MissingStorageMetadata(String, String),
35    /// Metadata for call could not be found.
36    #[error(
37        "Metadata for call entry {0}_{1} could not be found. Make sure you are providing a valid substrate-based metadata"
38    )]
39    MissingCallMetadata(String, String),
40    /// Metadata for call could not be found.
41    #[error(
42        "Metadata for runtime API entry {0}_{1} could not be found. Make sure you are providing a valid substrate-based metadata"
43    )]
44    MissingRuntimeApiMetadata(String, String),
45    /// Call variant must have all named fields.
46    #[error(
47        "Call variant for type {0} must have all named fields. Make sure you are providing a valid substrate-based metadata"
48    )]
49    InvalidCallVariant(u32),
50    /// Type should be an variant/enum.
51    #[error(
52        "{0} type should be an variant/enum type. Make sure you are providing a valid substrate-based metadata"
53    )]
54    InvalidType(String),
55    /// Extrinsic call type could not be found.
56    #[error(
57        "Extrinsic call type could not be found. Make sure you are providing a valid substrate-based metadata"
58    )]
59    MissingCallType,
60    /// There are too many or too few hashers.
61    #[error(
62        "Could not generate functions for storage entry {storage_entry_name}. There are {key_count} keys, but only {hasher_count} hashers. The number of hashers must equal the number of keys or be exactly 1."
63    )]
64    InvalidStorageHasherCount {
65        /// The name of the storage entry
66        storage_entry_name: String,
67        /// Number of keys
68        key_count: usize,
69        /// Number of hashers
70        hasher_count: usize,
71    },
72    /// Cannot generate types.
73    #[error("Type Generation failed: {0}")]
74    TypeGeneration(#[from] TypegenError),
75    /// Error when generating metadata from Wasm-runtime
76    #[error("Failed to generate metadata from wasm file. reason: {0}")]
77    Wasm(String),
78    /// Other error.
79    #[error("Other error: {0}")]
80    Other(String),
81}
82
83impl CodegenError {
84    /// Fetch the location for this error.
85    // Todo: Probably worth storing location outside of the variant,
86    // so that there's a common way to set a location for some error.
87    fn get_location(&self) -> Span {
88        match self {
89            Self::InvalidModule(span) => *span,
90            Self::TypeGeneration(TypegenError::InvalidSubstitute(err)) => err.span,
91            Self::InvalidTypePath(_, err) => err.span(),
92            _ => proc_macro2::Span::call_site(),
93        }
94    }
95    /// Render the error as an invocation of syn::compile_error!.
96    pub fn into_compile_error(self) -> TokenStream2 {
97        let msg = self.to_string();
98        let span = self.get_location();
99        syn::Error::new(span, msg).into_compile_error()
100    }
101}