@@ -21,7 +21,7 @@ pub mod lexer;
2121use std:: { error, fmt} ;
2222
2323pub use analysis:: { CheckErrorKind , StaticCheckError } ;
24- pub use ast:: { ParseError , ParseErrors , ParseResult } ;
24+ pub use ast:: { ParseError , ParseErrorKind , ParseResult } ;
2525pub use cost:: CostErrors ;
2626pub use lexer:: LexerError ;
2727#[ cfg( feature = "rusqlite" ) ]
@@ -33,8 +33,12 @@ use crate::types::{FunctionIdentifier, Value};
3333
3434pub type StackTrace = Vec < FunctionIdentifier > ;
3535
36+ /// Wraps error types that do not implement [`PartialEq`], enabling their
37+ /// use in enums that implement the trait. Any two `IncomparableError` values
38+ /// are always considered unequal.
3639#[ derive( Debug ) ]
3740pub struct IncomparableError < T > {
41+ /// The wrapped error value.
3842 pub err : T ,
3943}
4044
@@ -52,70 +56,141 @@ pub enum VmExecutionError {
5256 /// violating type or resource constraints (e.g., excessive stack depth).
5357 /// The `CheckErrorKind` wraps the specific type-checking error encountered at runtime.
5458 Unchecked ( CheckErrorKind ) ,
55- Interpreter ( InterpreterError ) ,
59+ /// A critical, unrecoverable bug within the VM's internal logic.
60+ ///
61+ /// The presence of this error indicates a violation of one of the VM's
62+ /// invariants or a corrupted state. This is **not** an error in the user's
63+ /// Clarity code, but a bug in the VM's Rust implementation.
64+ ///
65+ /// # Example
66+ /// The VM's evaluation loop attempts to `pop` from an empty internal call stack,
67+ /// indicating a mismatch in function entry/exit logic.
68+ Internal ( VmInternalError ) ,
5669 /// Errors that occur during runtime execution of Clarity code, such as arithmetic errors or
5770 /// invalid operations, expected as part of contract evaluation.
5871 /// The `RuntimeErrorType` wraps the specific runtime error, and the `Option<StackTrace>` provides
5972 /// an optional stack trace for debugging, if available.
60- Runtime ( RuntimeErrorType , Option < StackTrace > ) ,
73+ Runtime ( RuntimeError , Option < StackTrace > ) ,
6174 /// Errors triggered during Clarity contract evaluation that cause early termination with
6275 /// insufficient results (e.g., unwrapping an empty `Option`).
6376 /// The `EarlyReturnError` wraps the specific early return condition, detailing the premature
6477 /// termination cause.
6578 EarlyReturn ( EarlyReturnError ) ,
6679}
6780
68- /// InterpreterErrors are errors that *should never* occur.
69- /// Test executions may trigger these errors.
81+ /// Represents an internal, unrecoverable error within the Clarity VM.
82+ ///
83+ /// These errors signify a bug in the VM's logic or a violation of its internal
84+ /// invariants. They are not meant to be caught or handled by Clarity contracts.
7085#[ derive( Debug , PartialEq ) ]
71- pub enum InterpreterError {
86+ pub enum VmInternalError {
87+ /// Raised when the VM encounters an invalid or malformed `SymbolicExpression`
88+ /// e.g., bad variable name or missing argument.
89+ /// The `String` provides a message describing the specific issue.
7290 BadSymbolicRepresentation ( String ) ,
73- InterpreterError ( String ) ,
91+ /// A generic, unexpected internal error, indicating a logic failure within
92+ /// the VM.
93+ /// The `String` provides a message describing the specific failure.
94+ InvariantViolation ( String ) , // TODO: merge with VmInternalError::Expect
95+ /// The VM failed to produce the final `AssetMap` when finalizing the
96+ /// execution environment for a transaction.
7497 FailedToConstructAssetTable ,
98+ /// The VM failed to produce the final `EventBatch` when finalizing the
99+ /// execution environment for a transaction.
75100 FailedToConstructEventBatch ,
101+ /// An error occurred during an interaction with the database.
102+ /// The parameter contains the corresponding SQLite error.
76103 #[ cfg( feature = "rusqlite" ) ]
77104 SqliteError ( IncomparableError < SqliteError > ) ,
105+ /// The file path provided for the MARF database is invalid because it
106+ /// contains non-UTF-8 characters.
78107 BadFileName ,
108+ /// The VM failed to create the necessary directory for the MARF persistent
109+ /// storage. Likely due to a file system permissions error or an invalid path
79110 FailedToCreateDataDirectory ,
111+ /// A failure occurred within the MARF implementation.
112+ /// The `String` provides a message describing the specific failure.
80113 MarfFailure ( String ) ,
114+ /// Failed to construct a tuple value from provided data because it did not
115+ /// match the expected type signature.
81116 FailureConstructingTupleWithType ,
117+ /// Failed to construct a list value from provided data because it
118+ /// did not match the expected type signature.
82119 FailureConstructingListWithType ,
120+ /// An STX transfer failed due to insufficient balance.
83121 InsufficientBalance ,
122+ /// A generic error occurred during a database operation.
123+ /// The `String` represents a descriptive message detailing the specific issue.
84124 DBError ( String ) ,
125+ /// An internal expectation or assertion failed. This is used for conditions
126+ /// that are believed to be unreachable but are handled gracefully to prevent
127+ /// a panic.
128+ /// The `String` provides a message describing the failed expectation.
85129 Expect ( String ) ,
86130}
87131
88- /// RuntimeErrors are errors that smart contracts are expected
89- /// to be able to trigger during execution (e.g., arithmetic errors)
132+ /// Runtime errors that Clarity smart contracts are expected to trigger during execution in the virtual
133+ /// machine, such as arithmetic errors, invalid operations, or blockchain-specific issues. These errors
134+ /// are distinct from static analysis errors and occur during dynamic evaluation of contract code.
90135#[ derive( Debug , PartialEq ) ]
91- pub enum RuntimeErrorType {
136+ pub enum RuntimeError {
137+ /// A generic arithmetic error encountered during contract execution.
138+ /// The `String` represents a descriptive message detailing the specific arithmetic issue.
92139 Arithmetic ( String ) ,
140+ /// An arithmetic operation exceeded the maximum value for the data type (e.g., `u128`).
93141 ArithmeticOverflow ,
142+ /// An arithmetic operation resulted in a value below zero for an unsigned type.
94143 ArithmeticUnderflow ,
144+ /// Attempt to increase token supply beyond the maximum limit.
145+ /// The first u128 represents the attempted new supply (current supply plus increase),
146+ /// and the second represents the maximum allowed supply.
95147 SupplyOverflow ( u128 , u128 ) ,
148+ /// Attempt to decrease token supply below zero.
149+ /// The first `u128` represents the current token supply, and the second represents the attempted decrease amount.
96150 SupplyUnderflow ( u128 , u128 ) ,
151+ /// Attempt to divide or compute modulo by zero.
97152 DivisionByZero ,
98- // error in parsing types
99- ParseError ( String ) ,
100- // error in parsing the AST
153+ /// Failure to parse types dynamically during contract execution.
154+ /// The `String` represents the specific parsing issue, such as invalid data formats.
155+ TypeParseFailure ( String ) ,
156+ /// Failure to parse the abstract syntax tree (AST) during dynamic evaluation.
157+ /// The `Box<ParseError>` wraps the specific parsing error encountered, detailing code interpretation issues.
101158 ASTError ( Box < ParseError > ) ,
159+ /// The call stack exceeded the virtual machine's maximum depth.
102160 MaxStackDepthReached ,
161+ /// The execution context depth exceeded the virtual machine's limit.
103162 MaxContextDepthReached ,
163+ /// Attempt to construct an invalid or unsupported type at runtime (e.g., malformed data structure).
104164 BadTypeConstruction ,
165+ /// Reference to an invalid or out-of-bounds block height.
166+ /// The `String` represents the string representation of the queried block height that was invalid.
105167 BadBlockHeight ( String ) ,
168+ /// Attempt to interact with a non-existent token (e.g., in NFT or fungible token operations).
106169 NoSuchToken ,
170+ /// Feature or function not yet implemented in the virtual machine.
107171 NotImplemented ,
172+ /// No caller principal available in the current execution context.
108173 NoCallerInContext ,
174+ /// No sender principal available in the current execution context.
109175 NoSenderInContext ,
176+ /// Invalid name-value pair in contract data (e.g., map keys).
177+ /// The `&'static str` represents the name of the invalid pair, and the `String` represents the offending value.
110178 BadNameValue ( & ' static str , String ) ,
179+ /// Reference to a non-existent block header hash.
180+ /// The `BlockHeaderHash` represents the unknown block header hash.
111181 UnknownBlockHeaderHash ( BlockHeaderHash ) ,
182+ /// Invalid block hash provided (e.g., incorrect format or length).
183+ /// The `Vec<u8>` represents the invalid block hash data.
112184 BadBlockHash ( Vec < u8 > ) ,
185+ /// Failed to unwrap an `Optional` (`none`) or `Response` (`err` or `ok`) Clarity value.
113186 UnwrapFailure ,
187+ /// Attempt to set metadata (e.g., for NFTs or tokens) that was already initialized.
114188 MetadataAlreadySet ,
115- // pox-locking errors
189+ /// Interaction with a deprecated or inactive Proof of Transfer (PoX) contract.
116190 DefunctPoxContract ,
191+ /// Attempt to lock STX for stacking when already locked in an active PoX cycle.
117192 PoxAlreadyLocked ,
118-
193+ /// Block time unavailable during execution.
119194 BlockTimeNotAvailable ,
120195}
121196
@@ -146,7 +221,7 @@ impl PartialEq<VmExecutionError> for VmExecutionError {
146221 ( VmExecutionError :: Runtime ( x, _) , VmExecutionError :: Runtime ( y, _) ) => x == y,
147222 ( VmExecutionError :: Unchecked ( x) , VmExecutionError :: Unchecked ( y) ) => x == y,
148223 ( VmExecutionError :: EarlyReturn ( x) , VmExecutionError :: EarlyReturn ( y) ) => x == y,
149- ( VmExecutionError :: Interpreter ( x) , VmExecutionError :: Interpreter ( y) ) => x == y,
224+ ( VmExecutionError :: Internal ( x) , VmExecutionError :: Internal ( y) ) => x == y,
150225 _ => false ,
151226 }
152227 }
@@ -170,7 +245,7 @@ impl fmt::Display for VmExecutionError {
170245 }
171246}
172247
173- impl fmt:: Display for RuntimeErrorType {
248+ impl fmt:: Display for RuntimeError {
174249 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
175250 write ! ( f, "{self:?}" )
176251 }
@@ -182,7 +257,7 @@ impl error::Error for VmExecutionError {
182257 }
183258}
184259
185- impl error:: Error for RuntimeErrorType {
260+ impl error:: Error for RuntimeError {
186261 fn source ( & self ) -> Option < & ( dyn error:: Error + ' static ) > {
187262 None
188263 }
@@ -191,30 +266,30 @@ impl error::Error for RuntimeErrorType {
191266impl From < ParseError > for VmExecutionError {
192267 fn from ( err : ParseError ) -> Self {
193268 match * err. err {
194- ParseErrors :: InterpreterFailure => VmExecutionError :: from ( InterpreterError :: Expect (
269+ ParseErrorKind :: InterpreterFailure => VmExecutionError :: from ( VmInternalError :: Expect (
195270 "Unexpected interpreter failure during parsing" . into ( ) ,
196271 ) ) ,
197- _ => VmExecutionError :: from ( RuntimeErrorType :: ASTError ( Box :: new ( err) ) ) ,
272+ _ => VmExecutionError :: from ( RuntimeError :: ASTError ( Box :: new ( err) ) ) ,
198273 }
199274 }
200275}
201276
202277impl From < CostErrors > for VmExecutionError {
203278 fn from ( err : CostErrors ) -> Self {
204279 match err {
205- CostErrors :: InterpreterFailure => VmExecutionError :: from ( InterpreterError :: Expect (
280+ CostErrors :: InterpreterFailure => VmExecutionError :: from ( VmInternalError :: Expect (
206281 "Interpreter failure during cost calculation" . into ( ) ,
207282 ) ) ,
208- CostErrors :: Expect ( s) => VmExecutionError :: from ( InterpreterError :: Expect ( format ! (
283+ CostErrors :: Expect ( s) => VmExecutionError :: from ( VmInternalError :: Expect ( format ! (
209284 "Interpreter failure during cost calculation: {s}"
210285 ) ) ) ,
211286 other_err => VmExecutionError :: from ( CheckErrorKind :: from ( other_err) ) ,
212287 }
213288 }
214289}
215290
216- impl From < RuntimeErrorType > for VmExecutionError {
217- fn from ( err : RuntimeErrorType ) -> Self {
291+ impl From < RuntimeError > for VmExecutionError {
292+ fn from ( err : RuntimeError ) -> Self {
218293 VmExecutionError :: Runtime ( err, None )
219294 }
220295}
@@ -237,9 +312,9 @@ impl From<EarlyReturnError> for VmExecutionError {
237312 }
238313}
239314
240- impl From < InterpreterError > for VmExecutionError {
241- fn from ( err : InterpreterError ) -> Self {
242- VmExecutionError :: Interpreter ( err)
315+ impl From < VmInternalError > for VmExecutionError {
316+ fn from ( err : VmInternalError ) -> Self {
317+ VmExecutionError :: Internal ( err)
243318 }
244319}
245320
@@ -272,15 +347,13 @@ mod test {
272347 ) ) ) )
273348 ) ;
274349 assert_eq ! (
275- VmExecutionError :: Interpreter ( InterpreterError :: InterpreterError ( "" . to_string( ) ) ) ,
276- VmExecutionError :: Interpreter ( InterpreterError :: InterpreterError ( "" . to_string( ) ) )
350+ VmExecutionError :: Internal ( VmInternalError :: InvariantViolation ( "" . to_string( ) ) ) ,
351+ VmExecutionError :: Internal ( VmInternalError :: InvariantViolation ( "" . to_string( ) ) )
277352 ) ;
278353 assert ! (
279354 VmExecutionError :: EarlyReturn ( EarlyReturnError :: UnwrapFailed ( Box :: new( Value :: Bool (
280355 true
281- ) ) ) ) != VmExecutionError :: Interpreter ( InterpreterError :: InterpreterError (
282- "" . to_string( )
283- ) )
356+ ) ) ) ) != VmExecutionError :: Internal ( VmInternalError :: InvariantViolation ( "" . to_string( ) ) )
284357 ) ;
285358 }
286359}
0 commit comments