Value-based Error Handling
Relevant source files
The following files were used as context for generating this wiki page:
Sploosh implements a strict "errors are values" philosophy, where fallible operations return a Result<T, E> type rather than using exceptions or panics in safe code. This approach ensures that all potential failure points are explicit in the source code, facilitating high accuracy for both human developers and AI coding agents. By treating errors as standard data values, the language enforces structural handling of failures through pattern matching and propagation operators.
The system is designed to provide safety-first execution without hidden control flow. In on-chain environments (EVM/Solana), the compiler enforces these rules to prevent non-deterministic behavior and provide robust reentrancy protection. Errors are integrated into the core syntax, utilizing familiar vocabulary like Result and the error propagation operator ? to maintain consistency across the language's dual-target compilation model.
Sources: README.md:38-39, VISION.md:83-84, VISION.md:120-121, SECURITY.md:68-70
The Result Pattern
Every fallible operation in Sploosh is required to return a Result<T, E>. This structure forces the caller to acknowledge the possibility of failure. The language grammar specifically supports this via the Result type, which is frequently used in both native application code and smart contract modules.
Component Structure
The following diagram illustrates how a fallible function interacts with the Result value to return either success or a specific error variant.
The standard workflow involves wrapping successful data in an Ok variant and failure details in an Err variant.
Sources: README.md:38-39, README.md:65, crates/sploosh-parser/src/lib.rs:188-193
Error Propagation and Pipelines
Sploosh provides specialized syntax to manage the flow of error values without verbose boilerplate. The two primary mechanisms are the ? operator and the pipeline operator |>.
The Propagation Operator ?
The ? operator is used for early return of error values. When applied to a Result, it extracts the value if successful or immediately returns the error from the current function.
Pipeline Integration
The pipeline operator |> allows for left-to-right processing of data. When combined with the propagation operator (|> ...?), it enables per-stage error checking within a single expression.
| Operator | Usage | Behavioral Description |
|---|---|---|
? | expr? | Unwraps Ok(T) or returns Err(E) to the calling function scope. |
|> | x |> f | Passes x as the first argument to function f. |
|>? | x |> f? | Pipes x to f and immediately propagates any resulting error. |
Sources: README.md:46-48, VISION.md:107-108, crates/sploosh-parser/src/lib.rs:460-466
Match Expressions and Pattern Matching
The match expression is the primary structural tool for handling Result values. It allows developers to destructure the variants and handle success and failure cases explicitly. The parser enforces that match expressions follow a specific grammar for patterns, including support for guards and destructuring.
Error Handling Flow
The sequence below demonstrates how a match expression handles a fallible call.
Compiler and Lexer Error Representation
The Sploosh compiler bootstrap implementation in Rust mirrors the language's philosophy by using structured error types for its internal stages. The lexer and parser utilize specific error structs to track failure locations in source code via Span objects.
Data Structures for Diagnostics
| Struct | Field | Type | Description |
|---|---|---|---|
LexError | message | String | Human-readable description of the lexing failure. |
LexError | span | Span | The start and end byte offsets in the source text. |
ParseError | message | String | Description of the syntax violation. |
ParseError | span | Span | The source location where the parser failed. |
Sources: crates/sploosh-lexer/src/lib.rs:163-166, crates/sploosh-parser/src/lib.rs:7-11, crates/AGENTS.md:65-67
On-chain Error Constraints
In the onchain mod context, error handling is critical for transaction integrity. Fallible operations such as storage::get or chain::call return Result values that must be handled to prevent unintended contract states. The compiler rejects non-deterministic operations that might cause silent failures on-chain.
pub fn transfer(to: Address, amount: u256) -> Result<(), TokenError> {
let bal = storage::get(&self.balances, sender)?; // Propagation used here
if bal < amount {
return Err(TokenError::InsufficientBalance); // Value-based error return
}
// ... logic ...
Ok(())
}
Sources: README.md:57-65, VISION.md:106-107, SECURITY.md:68-71
Conclusion
Value-based error handling in Sploosh eliminates the unpredictability of traditional exception systems by making failures a first-class part of the data flow. By leveraging Result<T, E>, explicit propagation through the ? operator, and structured pattern matching, the language ensures that error states are detectable at compile time and manageable at runtime. This architecture is central to Sploosh's goal of providing a predictable environment for both AI-generated code and high-stakes web3 applications.